背景
在開(kāi)發(fā)過(guò)程中,對(duì)象數(shù)組的排序會(huì)經(jīng)常用到。如果想要實(shí)現(xiàn)多個(gè)字段按優(yōu)先級(jí)排序的話,如何處理?這種情況比較少見(jiàn)。舉例來(lái)說(shuō),有以下對(duì)象數(shù)組:
const list = [
{
"title": "This is a deme page",
"name": "Aborn Jiang",
"age": 21
},
{
"title": "mindpress is a good framework",
"name": "John",
"age": 31
},
{
"title": "Goodness",
"name": "Aborn Jiang",
"age": 19
}
]
如果我們想按 name 字段排序,當(dāng)name 字段相同時(shí),再按title字段排序。
放得更加寬泛點(diǎn),可以按任意多字段排序。
單字段排序
如果只按name排序,那調(diào)用sort方法如下:
const sortedList = list.sort((a, b) =>
a.name.localeCompare(b.name)
)
兩字段排序
如果先按name排序,在name相同的情況下,再按 age排序,寫(xiě)法臺(tái)下:
const sortedList = list.sort((a, b) =>
a.name.localeCompare(b.name) || a.age - b.age
)
通用多字段排序
由兩字段再擴(kuò)展到任意字段,其實(shí)是我們需要分別判斷每個(gè)字段,當(dāng)前一個(gè)字段比較后不為 0,則返回;如果為 0表示繼續(xù)采用后一個(gè)字段進(jìn)行排序,通用寫(xiě)法如下:
export interface SortFields {
[field: string]: -1 | 1
}
export type SortOptions = SortFields
export const get = (obj: any, path: string): any => path.split('.').reduce((acc, part) => acc && acc[part], obj)
/**
* Sort list of items by givin options
* sort array of object by multi fields.
* example:
* const sortedArray = sortList(toBeSortedArray, { 'createTime': -1, 'title': 1 })
*/
export const sortList = (data: any[], params: SortOptions) => {
const comperable = new Intl.Collator(params.$locale as string, {
numeric: params.$numeric as boolean,
caseFirst: params.$caseFirst as any,
sensitivity: params.$sensitivity as any
})
const keys = Object.keys(params)
data = data.sort((a, b) => {
let res = 0;
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const values = [get(a, key), get(b, key)]
.map((value) => {
// `null` values are treated as `"null"` strings and ordered alphabetically
// Turn `null` values into `undefined` so they place at the end of the list
if (value === null) {
return undefined
}
// Convert Date object to ISO string
if (value instanceof Date) {
return value.toISOString()
}
return value
})
if (params[key as keyof SortOptions] === -1) {
values.reverse()
}
res = comperable.compare(values[0], values[1])
if (res != 0) return res;
}
return res;
})
return data
}
調(diào)用舉例:
sortedArray = sortList(toBeSortedArray, { 'createTime': -1, 'title': 1 })
先按 createTime 從最新到最舊排序(逆序,所以用-1),在時(shí)間相同的情況下,使用title排序(正序,用1)
代碼見(jiàn): https://github.com/aborn/mindpress/blob/main/mindpress-fe/server/utils/query/sort.ts