mirror of
https://github.com/toss/es-toolkit.git
synced 2024-11-24 03:32:58 +03:00
feat(orderBy): Add orderBy (#123)
* feat(orderBy): add orderBy function * feat(orderBy): add orderBy test code * feat(orderBy): add orderBy bench * feat(orderBy): add orderBy function docs * feat(orderBy): add orderBy vitepress docs * fix: test function & add the extend orders feature * Update src/array/orderBy.ts --------- Co-authored-by: Sojin Park <raon0211@gmail.com> Co-authored-by: Sojin Park <raon0211@toss.im>
This commit is contained in:
parent
1918eec3d9
commit
1eada4d85d
25
benchmarks/orderBy.bench.ts
Normal file
25
benchmarks/orderBy.bench.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { orderBy as orderByToolkit } from 'es-toolkit';
|
||||
import { orderBy as orderByLodash } from 'lodash';
|
||||
|
||||
describe('orderBy', () => {
|
||||
bench('es-toolkit/orderBy', () => {
|
||||
const users = [
|
||||
{ user: 'fred', age: 48 },
|
||||
{ user: 'barney', age: 34 },
|
||||
{ user: 'fred', age: 40 },
|
||||
{ user: 'barney', age: 36 },
|
||||
];
|
||||
orderByToolkit(users, ['user', 'age'], ['asc', 'asc']);
|
||||
});
|
||||
|
||||
bench('lodash/orderBy', () => {
|
||||
const users = [
|
||||
{ user: 'fred', age: 48 },
|
||||
{ user: 'barney', age: 34 },
|
||||
{ user: 'fred', age: 40 },
|
||||
{ user: 'barney', age: 36 },
|
||||
];
|
||||
orderByLodash(users, ['user', 'age'], ['asc', 'asc']);
|
||||
});
|
||||
});
|
@ -66,6 +66,7 @@ function sidebar(): DefaultTheme.Sidebar {
|
||||
{ text: 'keyBy', link: '/reference/array/keyBy' },
|
||||
{ text: 'minBy', link: '/reference/array/minBy' },
|
||||
{ text: 'maxBy', link: '/reference/array/maxBy' },
|
||||
{ text: 'orderBy', link: '/reference/array/orderBy' },
|
||||
{ text: 'partition', link: '/reference/array/partition' },
|
||||
{ text: 'sample', link: '/reference/array/sample' },
|
||||
{ text: 'sampleSize', link: '/reference/array/sampleSize' },
|
||||
|
@ -65,6 +65,7 @@ function sidebar(): DefaultTheme.Sidebar {
|
||||
{ text: 'keyBy', link: '/ko/reference/array/keyBy' },
|
||||
{ text: 'minBy', link: '/ko/reference/array/minBy' },
|
||||
{ text: 'maxBy', link: '/ko/reference/array/maxBy' },
|
||||
{ text: 'orderBy', link: '/ko/reference/array/orderBy' },
|
||||
{ text: 'partition', link: '/ko/reference/array/partition' },
|
||||
{ text: 'sample', link: '/ko/reference/array/sample' },
|
||||
{ text: 'sampleSize', link: '/ko/reference/array/sampleSize' },
|
||||
|
43
docs/ko/reference/array/orderBy.md
Normal file
43
docs/ko/reference/array/orderBy.md
Normal file
@ -0,0 +1,43 @@
|
||||
# orderBy
|
||||
|
||||
여러 속성과 해당 순서 방향에 따라 객체 배열을 정렬해요.
|
||||
|
||||
이 함수는 객체 배열, 정렬할 키의 배열, 그리고 정렬 방향의 배열을 받아요.
|
||||
각 키에 대해 해당 방향('asc'는 오름차순, 'desc'는 내림차순)에 따라 정렬된 배열을 반환해요.
|
||||
키의 값이 동일한 경우 다음 키를 기준으로 정렬 순서를 결정해요.
|
||||
|
||||
## Signature
|
||||
|
||||
```typescript
|
||||
function orderBy<T>(collection: T[], keys: Array<keyof T>, orders: Order[]): T[];
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
- `collection` (`T[]`): 정렬할 객체 배열.
|
||||
- `keys` (`Array<keyof T>`): 정렬할 키(속성) 배열.
|
||||
- `orders` (`Order[]`): 각 키에 대한 정렬 방향 배열('asc'는 오름차순, 'desc'는 내림차순).
|
||||
|
||||
### Returns
|
||||
|
||||
(`T[]`) 정렬된 배열.
|
||||
|
||||
## Examples
|
||||
|
||||
```typescript
|
||||
const users = [
|
||||
{ user: 'fred', age: 48 },
|
||||
{ user: 'barney', age: 34 },
|
||||
{ user: 'fred', age: 40 },
|
||||
{ user: 'barney', age: 36 },
|
||||
];
|
||||
|
||||
const result = orderBy(users, ['user', 'age'], ['asc', 'desc']);
|
||||
// result will be:
|
||||
// [
|
||||
// { user: 'barney', age: 36 },
|
||||
// { user: 'barney', age: 34 },
|
||||
// { user: 'fred', age: 48 },
|
||||
// { user: 'fred', age: 40 },
|
||||
// ]
|
||||
```
|
44
docs/reference/array/orderBy.md
Normal file
44
docs/reference/array/orderBy.md
Normal file
@ -0,0 +1,44 @@
|
||||
# orderBy
|
||||
|
||||
Sorts an array of objects based on multiple properties and their corresponding order directions.
|
||||
|
||||
This function takes an array of objects, an array of keys to sort by, and an array of order directions.
|
||||
It returns the sorted array, ordering by each key according to its corresponding direction
|
||||
('asc' for ascending or 'desc' for descending). If values for a key are equal,
|
||||
it moves to the next key to determine the order.
|
||||
|
||||
## Signature
|
||||
|
||||
```typescript
|
||||
function orderBy<T>(collection: T[], keys: Array<keyof T>, orders: Order[]): T[];
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
- `collection` (`T[]`): The array of objects to be sorted.
|
||||
- `keys` (`Array<keyof T>`): An array of keys (properties) by which to sort.
|
||||
- `orders` (`Order[]`): An array of order directions ('asc' for ascending or 'desc' for descending).
|
||||
|
||||
### Returns
|
||||
|
||||
(`T[]`) The sorted array.
|
||||
|
||||
## Examples
|
||||
|
||||
```typescript
|
||||
const users = [
|
||||
{ user: 'fred', age: 48 },
|
||||
{ user: 'barney', age: 34 },
|
||||
{ user: 'fred', age: 40 },
|
||||
{ user: 'barney', age: 36 },
|
||||
];
|
||||
|
||||
const result = orderBy(users, ['user', 'age'], ['asc', 'desc']);
|
||||
// result will be:
|
||||
// [
|
||||
// { user: 'barney', age: 36 },
|
||||
// { user: 'barney', age: 34 },
|
||||
// { user: 'fred', age: 48 },
|
||||
// { user: 'fred', age: 40 },
|
||||
// ]
|
||||
```
|
@ -9,7 +9,7 @@ export { dropRight } from './dropRight.ts';
|
||||
export { dropRightWhile } from './dropRightWhile.ts';
|
||||
export { dropWhile } from './dropWhile.ts';
|
||||
export { fill } from './fill.ts';
|
||||
export { forEachRight } from './forEachRight.ts'
|
||||
export { forEachRight } from './forEachRight.ts';
|
||||
export { groupBy } from './groupBy.ts';
|
||||
export { intersection } from './intersection.ts';
|
||||
export { intersectionBy } from './intersectionBy.ts';
|
||||
@ -17,6 +17,7 @@ export { intersectionWith } from './intersectionWith.ts';
|
||||
export { keyBy } from './keyBy.ts';
|
||||
export { maxBy } from './maxBy.ts';
|
||||
export { minBy } from './minBy.ts';
|
||||
export { orderBy } from './orderBy.ts';
|
||||
export { partition } from './partition.ts';
|
||||
export { sample } from './sample.ts';
|
||||
export { sampleSize } from './sampleSize.ts';
|
||||
|
76
src/array/orderBy.spec.ts
Normal file
76
src/array/orderBy.spec.ts
Normal file
@ -0,0 +1,76 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { orderBy } from './orderBy';
|
||||
|
||||
describe('orderBy', () => {
|
||||
it('should order objects by a single property in ascending order', () => {
|
||||
const users = [
|
||||
{ user: 'fred', age: 48 },
|
||||
{ user: 'barney', age: 34 },
|
||||
{ user: 'fred', age: 40 },
|
||||
{ user: 'barney', age: 36 },
|
||||
];
|
||||
|
||||
const result = orderBy(users, ['user'], ['asc']);
|
||||
|
||||
expect(result).toEqual([
|
||||
{ user: 'barney', age: 34 },
|
||||
{ user: 'barney', age: 36 },
|
||||
{ user: 'fred', age: 48 },
|
||||
{ user: 'fred', age: 40 },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should order objects by a single property in descending order', () => {
|
||||
const users = [
|
||||
{ user: 'fred', age: 48 },
|
||||
{ user: 'barney', age: 34 },
|
||||
{ user: 'fred', age: 40 },
|
||||
{ user: 'barney', age: 36 },
|
||||
];
|
||||
|
||||
const result = orderBy(users, ['user'], ['desc']);
|
||||
|
||||
expect(result).toEqual([
|
||||
{ user: 'fred', age: 48 },
|
||||
{ user: 'fred', age: 40 },
|
||||
{ user: 'barney', age: 34 },
|
||||
{ user: 'barney', age: 36 },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should order objects by multiple properties', () => {
|
||||
const users = [
|
||||
{ user: 'fred', age: 48 },
|
||||
{ user: 'barney', age: 34 },
|
||||
{ user: 'fred', age: 40 },
|
||||
{ user: 'barney', age: 36 },
|
||||
];
|
||||
|
||||
const result = orderBy(users, ['user', 'age'], ['asc', 'desc']);
|
||||
|
||||
expect(result).toEqual([
|
||||
{ user: 'barney', age: 36 },
|
||||
{ user: 'barney', age: 34 },
|
||||
{ user: 'fred', age: 48 },
|
||||
{ user: 'fred', age: 40 },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should extend orders if orders length is less than keys length', () => {
|
||||
const users = [
|
||||
{ user: 'fred', age: 48 },
|
||||
{ user: 'barney', age: 36 },
|
||||
{ user: 'fred', age: 40 },
|
||||
{ user: 'barney', age: 34 },
|
||||
];
|
||||
|
||||
const result = orderBy(users, ['user', 'age'], ['asc']);
|
||||
|
||||
expect(result).toEqual([
|
||||
{ user: 'barney', age: 34 },
|
||||
{ user: 'barney', age: 36 },
|
||||
{ user: 'fred', age: 40 },
|
||||
{ user: 'fred', age: 48 },
|
||||
]);
|
||||
});
|
||||
});
|
58
src/array/orderBy.ts
Normal file
58
src/array/orderBy.ts
Normal file
@ -0,0 +1,58 @@
|
||||
type Order = 'asc' | 'desc';
|
||||
|
||||
/**
|
||||
* Sorts an array of objects based on multiple properties and their corresponding order directions.
|
||||
*
|
||||
* This function takes an array of objects, an array of keys to sort by, and an array of order directions.
|
||||
* It returns the sorted array, ordering by each key according to its corresponding direction
|
||||
* ('asc' for ascending or 'desc' for descending). If values for a key are equal,
|
||||
* it moves to the next key to determine the order.
|
||||
*
|
||||
* @template T - The type of elements in the array.
|
||||
* @param {T[]} collection - The array of objects to be sorted.
|
||||
* @param {Array<keyof T>} keys - An array of keys (properties) by which to sort.
|
||||
* @param {Order[]} orders - An array of order directions ('asc' for ascending or 'desc' for descending).
|
||||
* @returns {T[]} - The sorted array.
|
||||
*
|
||||
* @example
|
||||
* // Sort an array of objects by 'user' in ascending order and 'age' in descending order.
|
||||
* const users = [
|
||||
* { user: 'fred', age: 48 },
|
||||
* { user: 'barney', age: 34 },
|
||||
* { user: 'fred', age: 40 },
|
||||
* { user: 'barney', age: 36 },
|
||||
* ];
|
||||
* const result = orderBy(users, ['user', 'age'], ['asc', 'desc']);
|
||||
* // result will be:
|
||||
* // [
|
||||
* // { user: 'barney', age: 36 },
|
||||
* // { user: 'barney', age: 34 },
|
||||
* // { user: 'fred', age: 48 },
|
||||
* // { user: 'fred', age: 40 },
|
||||
* // ]
|
||||
*/
|
||||
export function orderBy<T>(collection: T[], keys: Array<keyof T>, orders: Order[]): T[] {
|
||||
const compareValues = (a: T[keyof T], b: T[keyof T], order: Order) => {
|
||||
if (a < b) {
|
||||
return order === 'asc' ? -1 : 1;
|
||||
}
|
||||
if (a > b) {
|
||||
return order === 'asc' ? 1 : -1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
const effectiveOrders = keys.map((_, index) => orders[index] || orders[orders.length - 1]);
|
||||
|
||||
return collection.slice().sort((a, b) => {
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i];
|
||||
const order = effectiveOrders[i];
|
||||
const result = compareValues(a[key], b[key], order);
|
||||
if (result !== 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue
Block a user