简体   繁体   English

按属性对对象数组进行排序以匹配提供的列表

[英]Sorting array of objects by property to match a provided list

Given an array of objects and a list of values, I want to effectively sort the object so that values of a unique property (say key ) follows the order of values in the list.给定一个对象数组和一个值列表,我想有效地对 object 进行排序,以便唯一属性(比如key )的值遵循列表中值的顺序。

So for an array:所以对于一个数组:

const users = [
  { key: 'A', name: 'Alice' },
  { key: 'B', name: 'Bob' },
  { key: 'C', name: 'Charlie' },
]

I'd like the function to behave like this:我希望 function 的行为如下:

sortByList(['A', 'B', 'C'], users)
// -> Objects for Alice, Bob, Charlie

sortByList(['C', 'B', 'A'], users)
// -> Objects for Charlie, Bob, Alice

sortByList(['A', 'C', 'B'], users)
// -> Objects for Alice, Charlie, Bob

I came up with an implementation that uses Array::sort on the array and then inside Array::indexOf on the list.我想出了一个实现,它在数组上使用Array::sort ,然后在列表上的Array::indexOf内使用。

 const users = [ { key: 'A', name: 'Alice' }, { key: 'B', name: 'Bob' }, { key: 'C', name: 'Charlie' }, ] const sortByList = (list, arr) => arr.sort( (a, b) => list.indexOf(a.key) - list.indexOf(b.key) ); sortByList(['C', 'B', 'A'], users) console.log(users)

But I feel this is not an effective solution.但我觉得这不是一个有效的解决方案。 The time complexity is O(N^2*log(N)) which is rather high.时间复杂度为 O(N^2*log(N)) ,相当高。 Is there a better one?有更好的吗?

I do not care about in-place sorting or stability, imagine the array has tens to hundreds of items.我不关心就地排序或稳定性,想象数组有几十到几百个项目。

With the limitation, that you can guarantee the keys-list is definitely equal to keys from the users data, you can avoid any sorting and create a temporary map, to generate a new "sorted" array:有了限制,您可以保证键列表绝对等于用户数据中的键,您可以避免任何排序并创建一个临时 map,以生成一个新的“排序”数组:

 const users = [ { key: 'A', name: 'Alice' }, { key: 'B', name: 'Bob' }, { key: 'C', name: 'Charlie' } ] const orderList = ['A','B','C'] const sortByList = (list, arr) => { const tmpMap = arr.reduce((acc, item) => { acc[item.key] = item return acc }, {}); return list.map((key) => tmpMap[key]) } console.log( sortByList(orderList, users) )

You could take an object with the wanted order for the keys.您可以使用 object 和所需的密钥顺序。

By using an object you have an access complexity of O(1) vs O(n) by taking indexOf .通过使用 object,您可以通过indexOf获得 O(1) 与 O(n) 的访问复杂度。

 const users = [{ key: 'A', name: 'Alice' }, { key: 'B', name: 'Bob' }, { key: 'C', name: 'Charlie' }], sortByList = (list, arr) => { const order = Object.fromEntries(list.map((k, i) => [k, i])); return arr.sort((a, b) => order[a.key] - order[b.key]); }; console.log(sortByList(['A', 'B', 'C'], users)); // Alice, Bob, Charlie console.log(sortByList(['C', 'B', 'A'], users)); // Charlie, Bob, Alice console.log(sortByList(['A', 'C', 'B'], users)); // Alice, Charlie, Bob
 .as-console-wrapper { max-height: 100%;important: top; 0; }

Pretty sure it's not more efficient.很确定它不是更有效。 Also, it's prone to error if list contains values with no corresponding key or if arr contains an object with no corresponding key in list but that's the first alternative that comes to my mind:此外,如果list包含没有相应键的值,或者如果arr包含 object 而list中没有相应的键,则很容易出错,但这是我想到的第一个替代方案:

const sortByList = (list, arr) => {
  const sortedList = [];
  for (let i = 0; i < arr.length; i++) {
    sortedList[arr.findIndex((item) => item.key === list[i])] = arr[i];
  }
  return sortedList;
}

how about this?这个怎么样?

const sortByKeyAndList = (key, list, objects) => objects.sort((a, b) =>
list.findIndex(i => i === a[key]) - list.findIndex(i => i === b[key]))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM