我有一个与此类似的对象数组:
[
{
ref: "CTB98",
name: "Joe"
},
{
ref: "HTF76",
name: "Alice"
},
{
ref: "JHU90",
name: "Tom"
},
{
ref: "ADF56",
name: "Mary"
}
]
在另一个数组中,我有他们原本要处的确切顺序,由ref
属性引用:
["JHU90", "HTF76", "CTB98", "ADF56"]
我想重新排列第一个对象数组的顺序,以便每个对象上的ref值遵循与上面参考数组中的值相同的顺序。
我是计算机科学的新手,所以我会选择答案并对该技术进行最佳解释。
答案 0 :(得分:4)
当您进行排序时,将挑选数组中的两个项目并将它们进行比较以确定哪个项目应该首先出现。在这种情况下,必须在引用数组中的元素的索引之间进行比较。所以,你可以像这样对它们进行排序
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' } ]
注意:由于您是新手,我建议您阅读此wonderful answer。这就解释了为什么我们要减去索引值以及我们应该从比较元素的函数中返回什么。
答案 1 :(得分:2)
我认为您要创建由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);
&#13;
<pre id="result"></pre>
&#13;
使用涉及indexOf
或嵌套for循环/ .forEach
的各种方法将导致以二次方式O(n^2)
增加所需的时间。对于每个n
元素,您可能需要执行n
个操作。
创建一个哈希对象,该对象使用每个对象的ref
属性作为对象的键,允许ref
查找对象为常量时间操作O(1)
。哈希的创建是在线性时间O(n)
内完成的,因为插入哈希对象的O(1)
执行n
次。
完成哈希后,通过迭代&#34;命令&#34;来执行另一个O(n)
操作。 n
项的数组,对每个订单键执行O(1)
查找以获取最终数组。
因此,此方法的总体时间复杂度为O(2n)
,仍为O(n)
。
这是一个简化的解释,没有考虑hash table插入已分摊[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);
}
&#13;
100 "items:"
polynomialSort: 1.893ms
linearSort: 0.235ms
10000 "items:"
polynomialSort: 1954.783ms
linearSort: 2.205ms
答案 2 :(得分:0)
这个方法有点笨拙,但是它有效,因为它取决于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);
输出:
答案 3 :(得分:0)
如果对象和引荐来源网址不匹配,则更可取。
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;
}