【问题标题】:Sort an object array by custom order按自定义顺序对对象数组进行排序
【发布时间】:2018-04-25 17:53:04
【问题描述】:

我有一个对象数组,其中包含一个名为“CODE”的属性。

[
  {
   ID: 168,
   NAME: "First name",
   CODE: "AD"
  },
  {
   ID: 167,
   NAME: "Second name",
   CODE: "CC"
  },
  {
   ID: 169,
   NAME: "Third name",
   CODE: "CCM"
  },
  {
   ID: 170,
   NAME: "Fourth name",
   CODE: "CR"
  },
]

如何按自定义顺序对数组进行排序,例如:

var item_order = ["CCM","CR","AD","CC"];

尝试了各种方法都没有成功。请帮忙。

【问题讨论】:

  • 无法理解排序的顺序
  • 您是说要使用 var item_order 作为数组来比较以确定顺序吗?

标签: javascript angularjs underscore.js


【解决方案1】:

您可以将函数 sort 与函数 indexOf 一起使用。

var array = [  {   ID: 168,   NAME: "First name",   CODE: "AD"  },  {   ID: 167,   NAME: "Second name",   CODE: "CC"  },  {   ID: 169,   NAME: "Third name",   CODE: "CCM"  },  {   ID: 170,   NAME: "Fourth name",   CODE: "CR"  }],
    item_order = ["CCM","CR","AD","CC"];

array.sort((a, b) => item_order.indexOf(a.CODE) - item_order.indexOf(b.CODE));

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 是的,但是在@NinaScholz 和我自己的答案中提到了大型数组。
  • @ScottSauyet 是的,但这超出了范围。
  • 感谢您的回答。我想根据item_order专门通过CODE属性对数组进行排序。
  • @newb1849 是的,这个答案提供了您正在寻找的内容。
  • 我们知道这超出了范围吗?我假设该数组可能包含许多具有相同 CODE 值的元素,但这可能是错误的。我只是无法从问题本身来判断。对于一个大数组,会有O(n * log n)indexOf 的调用。如果数组很小,或者甚至固定为与排序数组相同的元素计数,那么显然除了这个解决方案之外没有任何理由。我当然不是说它有什么问题。我只是想说明它的局限性。
【解决方案2】:

对于大型数组,我建议使用一个对象作为索引。

var array = [{ ID: 168, NAME: "First name", CODE: "AD" }, { ID: 167, NAME: "Second name", CODE: "CC" }, { ID: 169, NAME: "Third name", CODE: "CCM" }, { ID: 170, NAME: "Fourth name", CODE: "CR" }],
    item_order = ["CCM", "CR", "AD", "CC"],
    order = item_order.reduce((r, k, v) => Object.assign(r, { [k]: v }), {});

array.sort((a, b) => order[a.CODE] - order[b.CODE]);

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案3】:

    您将使用array.sort(customSort),其中:

    function customSort(a,b)
    {
        a = item_order.indexOf(a.CODE);
        b = item_order.indexOf(b.CODE);
    
        return a - b;
    }
    

    【讨论】:

      【解决方案4】:

      var array = [
        {
         ID: 168,
         NAME: "First name",
         CODE: "AD"
        },
        {
         ID: 167,
         NAME: "Second name",
         CODE: "CC"
        },
        {
         ID: 169,
         NAME: "Third name",
         CODE: "CCM"
        },
        {
         ID: 170,
         NAME: "Fourth name",
         CODE: "CR"
        },
      ];
      
      var sortOrder =  ["CCM","CR","AD","CC"];
      
      var sorted = array.sort((a, b) => sortOrder.indexOf(a.CODE) - sortOrder.indexOf(a.CODE));
      
      console.log(sorted);

      【讨论】:

      • 这是错误!应该是var sorted = array.sort((a, b) => sortOrder.indexOf(a.CODE) - sortOrder.indexOf(b.CODE));
      【解决方案5】:

      如果你必须经常做这样的事情,你可以写一个小工具来帮忙:

      const array = [{ ID: 168, NAME: "First name", CODE: "AD" }, { ID: 167, NAME: "Second name", CODE: "CC" }, { ID: 169, NAME: "Third name", CODE: "CCM" }, { ID: 170, NAME: "Fourth name", CODE: "CR" },{ ID: 166, NAME: "Fifth name", CODE: "CCM" }, { ID: 171, NAME: "Sixth name", CODE: "XXX" }, { ID: 172, NAME: "Seventh name", CODE: "CR" }]
      
      const sortOn = (prop, list) => {
        const order = list.reduce((obj, key, idx) => Object.assign(obj, { [key]: idx + 1}), {});
        const getVal = item => order[item[prop]] || Infinity
        
        return (a, b) => getVal(a) - getVal(b)
      }
      
      array.sort(sortOn('CODE', ["CCM", "CR", "AD", "CC"]))
      console.log(array)

      order 对象与 Nina Scholz 建议的非常相似。 idx + 1 而不仅仅是idx 的原因是为了简化下一行。该行使用Infinity 作为对那些键值未定义或不在排序列表中的人进行排序的一种方式。如果一开始就想要它们,可以使用0-Infinity

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-02-14
        • 1970-01-01
        • 2018-04-19
        • 2012-06-24
        相关资源
        最近更新 更多