typescript 如何按一系列键对对象数组进行稳定排序,以便保留前面每个键的顺序

gt0wga4j  于 2022-12-24  发布在  TypeScript
关注(0)|答案(1)|浏览(213)

我想创建一个通用函数,它可以使用键列表对对象数组进行排序,从而保留前一个键的顺序。下面是一个例子:

const input = [
  { a: 'aardvark', b: 'bear', c: 'camel', d: 1 },
  { a: 'anemone', b: 'bat', c: 'cobra', d: 6 },
  { a: 'aardvark', b: 'badger', c: 'camel', d: 2 },
  { a: 'alligator', b: 'bat', c: 'chicken', d: 2 },
  { a: 'alligator', b: 'beetle', c: 'cow', d: 1 },
  { a: 'alligator', b: 'bat', c: 'crab', d: 3 },
]

sortFunction(['a', 'b', 'd'], input)

// output
[
  { a: 'aardvark', b: 'badger', c: 'camel', d: 2 },
  { a: 'aardvark', b: 'bear', c: 'camel', d: 1 },
  { a: 'alligator', b: 'bat', c: 'chicken', d: 2 },
  { a: 'alligator', b: 'bat', c: 'crab', d: 3 },
  { a: 'alligator', b: 'beetle', c: 'cow', d: 1 },
  { a: 'anemone', b: 'bat', c: 'cobra', d: 6 },
]

要排序的第一个键是a,因此输出首先按a以降序正确地对数据排序。列表中的下一个键是b,因此对于a的值相同的任何项,b键仅用于重新排序a相同的项。最后,d仅用于重新排序ab值相同的物料。在此特定示例中,有两个物料的值分别为a: alligatorb: bat,因此包含d: 2的物料将放置在包含d: 3的物料之前。
我正在努力解决的问题是,如何将它变成一个泛型函数,它可以接受任何对象数组,并按照键列表对它们进行排序,其中键的值可以是字符串或数字,正如我在本例中所展示的。

afdcj2ne

afdcj2ne1#

一种方法是使用比较器回调函数对输入调用the sort() method,该函数按顺序比较每个键,直到找到一个确定排序顺序的键:

function sortFunction<K extends PropertyKey, T extends Record<K, string | number>>(
  keys: K[], objs: T[]
) {
  objs.sort((a, b) => {
    for (const k of keys) {
      if (a[k] < b[k]) return -1;
      if (a[k] > b[k]) return 1;
    }
    return 0;
  })
}

这是一个generic函数,它约束objs输入,以便已知对象数组在keys数组的键处具有stringnumber值。
您可以验证这是否能在您的示例输入上正常工作:

sortFunction(['a', 'b', 'd'], input);

console.log(input.map(v => JSON.stringify(v)).join("\n"));    
/*
"{"a":"aardvark","b":"badger","c":"camel","d":2}
{"a":"aardvark","b":"bear","c":"camel","d":1}
{"a":"alligator","b":"bat","c":"chicken","d":2}
{"a":"alligator","b":"bat","c":"crab","d":3}
{"a":"alligator","b":"beetle","c":"cow","d":1}
{"a":"anemone","b":"bat","c":"cobra","d":6}" ]
*/

Playground代码链接

相关问题