Skip to content

Commit

Permalink
feat: 新增 orderBy
Browse files Browse the repository at this point in the history
  • Loading branch information
fjc0k committed Jun 2, 2019
1 parent bb295ba commit cf948ea
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export * from './mapValues'
export * from './memoize'
export * from './noop'
export * from './omit'
export * from './orderBy'
export * from './pad'
export * from './parallel'
export * from './parseCSSValue'
Expand Down
78 changes: 78 additions & 0 deletions src/orderBy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { jestExpectEqual } from './enhanceJest'
import { orderBy, OrderByRuleType } from './orderBy'

const strData = ['hello', 'fjc', '20', '花间一壶酒', '=']

const numData = [-5, 4, 0, 1.2, 20]

const arrData = [
{ a: 'x', b: 3 },
{ a: 'y', b: 4 },
{ a: 'x', b: 1 },
{ a: 'z', b: 1 },
{ a: 'y', b: 2 },
]

test('desc 正常', () => {
jestExpectEqual(
orderBy(strData, {
iteratee: item => item.length,
type: OrderByRuleType.desc,
}),
['hello', '花间一壶酒', 'fjc', '20', '='],
)

jestExpectEqual(
orderBy(numData, {
iteratee: item => item,
type: OrderByRuleType.desc,
}),
[20, 4, 1.2, 0, -5],
)

jestExpectEqual(
orderBy(arrData, {
iteratee: item => item.b,
type: OrderByRuleType.desc,
}),
[
{ a: 'y', b: 4 },
{ a: 'x', b: 3 },
{ a: 'y', b: 2 },
{ a: 'x', b: 1 },
{ a: 'z', b: 1 },
],
)
})

test('asc 正常', () => {
jestExpectEqual(
orderBy(strData, {
iteratee: item => item.length,
type: OrderByRuleType.asc,
}),
['=', '20', 'fjc', 'hello', '花间一壶酒'],
)

jestExpectEqual(
orderBy(numData, {
iteratee: item => item,
type: OrderByRuleType.asc,
}),
[-5, 0, 1.2, 4, 20],
)

jestExpectEqual(
orderBy(arrData, {
iteratee: item => item.b,
type: OrderByRuleType.asc,
}),
[
{ a: 'x', b: 1 },
{ a: 'z', b: 1 },
{ a: 'y', b: 2 },
{ a: 'x', b: 3 },
{ a: 'y', b: 4 },
],
)
})
76 changes: 76 additions & 0 deletions src/orderBy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { castArray } from './castArray'
import { OneOrMore } from './enhanceType'

export enum OrderByRuleType {
/** 降序 */
desc = 'desc',
/** 升序 */
asc = 'asc',
}

export type OrderByRule<T> = {
/**
* 迭代函数。
*
* @param item 项目
* @returns 返回参与排序计算的值
*/
iteratee: (item: T) => any,
/**
* 类型。
*/
type: OrderByRuleType,
}

/**
* 允许指定一个或多个规则对数据进行排序。
*
* @param data 要排序的数据
* @param rules 一个或多个规则
* @returns 返回排序后的数据
* @example
* ```ts
* orderBy(
* ['x', 'xyz', 'xy'],
* {
* iteratee: item => item.length,
* type: OrderByRuleType.desc,
* },
* )
* // => ['xyz', 'xy', 'x']
* ```
*/
export function orderBy<T>(data: T[], rules: OneOrMore<OrderByRule<T>>): T[] {
return castArray(rules).reduce<T[]>(
(orderedData, rule) => {
const cachedKeys: T[] = []
const cachedValues: any[] = []
const cachedIteratee: OrderByRule<T>['iteratee'] = item => {
const index = cachedKeys.indexOf(item)
if (index === -1) {
const value = rule.iteratee(item)
cachedKeys.push(item)
cachedValues.push(value)
return value
}
return cachedValues[index]
}

const isAsc = rule.type === OrderByRuleType.asc

orderedData.sort((a, b) => {
a = cachedIteratee(a)
b = cachedIteratee(b)

return a === b ? 0 : (
a > b
? (isAsc ? 1 : -1)
: (isAsc ? -1 : 1)
)
})

return orderedData
},
data.slice(),
)
}

0 comments on commit cf948ea

Please sign in to comment.