【问题标题】:Sorting an Array of JavaScript Objects a Specific Order (using existing function)按特定顺序对 JavaScript 对象数组进行排序(使用现有函数)
【发布时间】:2013-09-17 20:21:03
【问题描述】:

给定一个对象数组:

{ 键:“一”, 价值:42 }, { 键:“d”, 价值:28 }, { 键:“c”, 价值:92 }, { 键:“b”, 价值:87 }

还有一个键数组:

["c", "a", "b", "d"]

是否有 ECMAScript 函数或第 3 方 JavaScript 库可让您排序 - 在一行/函数调用中 - 第一个对象数组,以 匹配键的顺序 在第二个数组中指定,结果是:

{ 键:“c”, 价值:92 }, { 键:“一”, 价值:42 }, { 键:“b”, 价值:87 }, { 键:“d”, 价值:28 }

其他提供函数或算法的问题:

类似/相关问题:

【问题讨论】:

  • 您是否尝试过结合使用 array.sort(function()) 和插入排序/选择排序?还是您只需要第三方解决方案?
  • 我在发布此问题后发现了一些其他问题的解决方案,并更新了问题。所以现在的目标是找到开箱即用的东西,而不是重新实现它。
  • 是否有 ECMAScript 函数或 3rd-party JavaScript 库可以让您...是一个购物问题,因此将被关闭。
  • 我很困惑为什么这个问题被投票结束。
  • 如果有本地方法可以做到这一点,有人会在其他问题之一中提到它。

标签: javascript jquery arrays sorting underscore.js


【解决方案1】:

只需使用indexOf 将密钥转换为正确的顺序:

var order = ["c", "a", "b", "d"];
_.sortBy(arr, function(obj){ 
    return _.indexOf(order, obj.key);
});

Fiddle

如果有很多键,那么从数组中创建一个哈希映射是有利的,例如:

var order = ["c", "a", "b", "d"];
var orderMap = {};
_.each(order, function(i) { orderMap[i] = _.indexOf(order, i); });

这使得键排序查找恒定时间而不是 O(n)。 (Fiddle)

【讨论】:

  • 很棒的答案。如此简单。
  • 我喜欢这个。在现有库中找到它仍然是一个很好的功能。我正在使用 CoffeeScript,所以这实际上是一个很好的单行:arr = _.sortBy arr, (obj) -> _.indexOf order, obj.key
  • @mkopala 您可以使用 _.mixin() underscorejs.org/#mixin 将自己的函数添加到下划线
  • 这个例子对我来说不是很清楚。这是一个让我很清楚的附加示例,jsfiddle.net/vsn32xp3
  • 这里是another version,它支持将未包含在order 数组中的数组项排列在已排序数组的后面重新排序。在您的版本中,未包含在 order 数组中的项目被放置在排序数组的前面。
【解决方案2】:

到目前为止提供了很好的答案。认为以下也可能是纯JS中的替代解决方案:

var arr = arr.sort(function(a,b) {
    return order.indexOf( a.key ) - order.indexOf( b.key );
    //for the sake of recent versions of Google Chrome use:
    //return a.key.charCodeAt(0) > b.key.charCodeAt(0); or return a.key.charCodeAt(0) - b.key.charCodeAt(0);
});

var arr = [
    {
        key: "a",
        value: 42
    },
    {
        key: "d",
        value: 28
    },
    {
        key: "c",
        value: 92
    },
    {
        key: "b",
        value: 87
    }
];

var order = ["c", "a", "b", "d"];

console.log( 'Original: ', JSON.stringify( arr ) );

var arr = arr.sort(function(a,b) {
      return order.indexOf( a.key ) - order.indexOf( b.key );
});

console.log( 'Ordered: ', JSON.stringify( arr ) );

【讨论】:

  • 在 Chrome 60 中,我无法直接从排序回调返回布尔值,我需要返回 -101 之一。
  • @BardiHarborow,return a.key.charCodeAt(0) > b.key.charCodeAt(0);return a.key.charCodeAt(0) - b.key.charCodeAt(0); 怎么样?
  • 我很确定这应该是 order.indexOf( a.key ) - order.indexOf( b.key ) 而不是布尔比较运算符。
  • 很好的答案,谢谢。
【解决方案3】:

const obj = [
    {
        key: "a",
        value: 42
    },
    {
        key: "d",
        value: 28
    },
    {
        key: "c",
        value: 92
    },
    {
        key: "b",
        value: 87
    }
]


const sortList = ["c", "a", "b", "d"];
    
    
const sortedObj = obj.sort((a, b) => {
    return (
        sortList.indexOf(a.key) - sortList.indexOf(b.key)
    );
});

console.log(sortedObj );

【讨论】:

    【解决方案4】:

    我不能说这是有效的方法,但是您可以将每个对象的key 用作另一个对象中属性的键。然后只需通过这些键访问它们。

    for (x = 0; x < objn.length; x++) {
        newobj[objn[x].key] = objn[x];
    }
    objn = [];
    for (x = 0; x < keys.length; x++) {
        objn.push(newobj[keys[x]]);
    }
    console.log(objn);
    

    http://jsfiddle.net/WdehF/

    【讨论】:

      【解决方案5】:
      // create hash map el.key -> index, to help us with direct access, avoid searching
      const hashMap = arr.reduce((acc, el, index) => { acc[el.id] = el; return acc }, {})
      
      // finally, map the ids to the final result
      const ids.map(id => hashMap[id])
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-26
        • 1970-01-01
        • 1970-01-01
        • 2018-02-07
        • 2018-07-07
        • 1970-01-01
        • 2019-11-04
        相关资源
        最近更新 更多