繁体   English   中英

根据另一个参考ID数组按属性对对象数组进行排序

[英]Sort an array of objects by property based on another array of reference IDs

我有一个类似的对象数组:

[
  {
    ref: "CTB98",
    name: "Joe"      
  },
  {
    ref: "HTF76",
    name: "Alice"      
  },
  {
    ref: "JHU90",
    name: "Tom"      
  },
  {
    ref: "ADF56",
    name: "Mary"      
  }
]

在另一个数组中,我具有它们应遵循的确切顺序,并由其ref属性ref

["JHU90", "HTF76", "CTB98", "ADF56"]  

我想重新排列第一个对象数组的顺序,以便每个对象上的ref值遵循与我上面的引用数组中的值相同的顺序。

我是计算机科学的新手,所以我将选择对该技术有最佳解释的答案。

排序时,将选择数组中的两个项目,并将它们进行比较以决定哪个应排在最前面。 在这种情况下,必须在引用数组中元素的索引之间进行比较。 因此,您可以像这样对它们进行排序

var data = [{ref: "CTB98", name: "Joe"},
            {ref: "HTF76", name: "Alice"},
            {ref: "JHU90", name: "Tom"},
            {ref: "ADF56", name: "Mary"}],
    references = ["JHU90", "HTF76", "CTB98", "ADF56"];

data.sort(function (item1, item2) {
    // Index of `item1.ref` in `references` and index of `item2.ref` in 
    // `references` are used to decide.
    return references.indexOf(item1.ref) - references.indexOf(item2.ref);
});

console.log(data);

产量

[ { ref: 'JHU90', name: 'Tom' },
  { ref: 'HTF76', name: 'Alice' },
  { ref: 'CTB98', name: 'Joe' },
  { ref: 'ADF56', name: 'Mary' } ]

注意:由于您是新手,因此建议您阅读此精彩答案 这就解释了为什么要减去索引值,以及从比较元素的函数中返回什么。

我认为您想创建由ref索引的对象的哈希,以防止O(n^2)时间。

此方法使您可以在O(n)时间内重新排序,但需要占用O(n)空间。

 var arr = [{ ref: "CTB98", name: "Joe" }, { ref: "HTF76", name: "Alice" }, { ref: "JHU90", name: "Tom" }, { ref: "ADF56", name: "Mary" }]; var order = ["JHU90", "HTF76", "CTB98", "ADF56"]; var result = reorder(arr, order); function reorder(arr, order) { var hash = Object.create(null); arr.forEach(function(obj) { hash[obj.ref] = obj; }); return order.map(function(refKey) { return hash[refKey]; }); } document.getElementById("result").innerHTML = JSON.stringify(result, null, 2); 
 <pre id="result"></pre> 

时间复杂度

使用涉及indexOf或嵌套for循环/ .forEach各种方法将导致所需的时间以二次方O(n^2) 对于n元素中的每个元素,您可能需要执行n操作。

创建一个使用每个对象的ref属性作为该对象的键的哈希对象,可以使ref查找对象是一个恒定时间操作O(1) 哈希的创建是在线性时间O(n) ,因为向哈希对象插入的操作是O(1)执行n次。

进行哈希处理后,您可以迭代n项的“订单”数组,并对每个订单键执行O(1)查找,以获取最终数组,从而执行另一个O(n)操作。

因此,此方法的总体时间复杂度将为O(2n) ,仍为O(n)

这是一个简化的解释,没有考虑哈希表插入的摊销[1] [2] O(1)


基准

 function polynomialSort(objs, order) { var arr = []; order.forEach(function(key) { objs.forEach(function(o) { if (o.ref === key) { arr.push(o); } }); }); return arr; } function linearSort(objs, order) { var hash = Object.create(null); objs.forEach(function(el) { hash[el.ref] = el; }); return order.map(function(el) { return hash[el]; }); } var lessObjs = []; var lessOrder = []; for (var i = 1; i < 100; i++) { lessObjs.push({ref:i}); lessOrder.push(i); } shuffle(lessOrder); console.log(100, "items:"); timer(polynomialSort, lessObjs, lessOrder); timer(linearSort, lessObjs, lessOrder); var moreObjs = []; var moreOrder = []; for (var i = 1; i < 10000; i++) { moreObjs.push({ref:i}); moreOrder.push(i); } shuffle(moreOrder); console.log(10000, "items:"); timer(polynomialSort, moreObjs, moreOrder); timer(linearSort, moreObjs, moreOrder); // http://stackoverflow.com/a/6274381/635411 function shuffle(o) { for (var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x); return o; } /** * Decorator function for timing a function. * @param {Function} f Function to be timed. */ function timer(f) { console.time(f.name); f.apply(null, [].slice.call(arguments, 1)); console.timeEnd(f.name); } 

100 "items:"
polynomialSort: 1.893ms
linearSort: 0.235ms
10000 "items:"
polynomialSort: 1954.783ms
linearSort: 2.205ms

此方法有点精巧,但可以用,因为它取决于JavaScript的Array.prototype.forEach将按索引顺序遍历元素的原理(请参阅jsfiddle ):

var objs = [
      {
        ref: "CTB98",
        name: "Joe"      
      },
      {
        ref: "HTF76",
        name: "Alice"      
      },
      {
        ref: "JHU90",
        name: "Tom"      
      },
      {
        ref: "ADF56",
        name: "Mary"      
      }
    ],
    order = ["JHU90", "HTF76", "CTB98", "ADF56"],
    arr = [];

order.forEach(function(key) {
    objs.forEach(function(o) {
        if(o.ref === key) {
            arr.push(o);   
        }
    });
});

console.log(arr);

输出:

产量

如果对象和引荐来源网址不匹配,则该选项更为可取。

function sortBy( items , ids ){

    let hash = {};
    let i = 0;

    for( i = 0; i <  items.length; i++ ){
        hash[ items[i].ref ] = items[i];
    }

    let orderedItems = [];
    for( i = 0; i <  ids.length; i++ ){
        if( hash[ids[i]]  ){
            orderedItems.push(hash[ids[i]]);
        }
    }

    return orderedItems;
}

暂无
暂无

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

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