我有一个对象数组,其中一些元素是另一个元素的克隆,因此它们具有引用原始元素的另一个属性的属性(简化示例):
var a = [{
id: 'x0',
name: 'Foo',
isClone: false,
wasCloned: true,
originalId: ''
}, {
id: 'y1',
name: 'Bar'.
isClone: false,
wasCloned: false,
originalId: ''
}, {
id: 'z2',
name: 'Foo',
isClone: true,
wasCloned: false,
originalId: 'x0'
}];
在这个例子中,第三个元素引用第一个元素的id - 这使它成为这个意义上的克隆。不幸的是,id不是增量/时间顺序的,基本上可以是任意随机字符串。
现在,手头的任务是以这样的方式对数组进行排序,以便克隆始终放置在数组位置右之前其原始位置。如果数组元素不是克隆,则排序应该照常进行。换句话说,一旦排序,此示例中的顺序将为 2,0,1 。
我试图弄清楚如何使用Array.sort
来解决这个问题,但却无法真正理解它。这基本上就是我所拥有的(它不起作用):
var sortedA = a.sort(function(one, other) {
var sorted;
if (one.id == other.originalId) {
sorted = -1;
} else {
sorted = 0;
}
return sorted;
});
非常感谢您对此的任何帮助。谢谢。
答案 0 :(得分:2)
您应该使用以下排序功能:
var sorted = a.sort(
function (a, b) {
var compareA = a.originalId || a.id;
var compareB = b.originalId || b.id;
if (compareA < compareB) {
return -1;
} else if (compareA > compareB) {
return 1;
} else {
return a.originalId !== '' ? -1 : 1;
}
}
);
可以使用功能工作的一个示例here。
答案 1 :(得分:1)
获取具有原始ID的所有对象,并保存没有的对象。
var others = [];
var data = a.filter(function(elem) {
if (elem.originalID !== '') {
return true;
} else {
others.push(elem); // keep a trace of elements without originalID
return false;
}
});
对它们进行排序,使它们全部打包在一起
data.sort(function(a, b) {
return a.originalID.localeCompare(b.originalID); //compare string
});
现在,您将所有包含相同originalID
的元素打包在一起。
然后,我们只需要在每个打包元素的末尾添加带有id
的元素,并使用相同的originalID
。
var originId = data[0].originalID; //get the first origin id
for(var i = 0; i < data.length; i++) {
var elem = data[i];
//the end of a packed list
if(originID !== elem.originalID) {
var val = others.find(function(e, index) { //find the element with the good id
if(return e.id === originID) {
others.splice(index, 1);//remove the element from the others array
return true;
} else {
return false;
}
});
data.splice(i, 0, val[0]); //insert it at the end of the packed list
originID = elem.originalID; //save for next loop
}
}
//just need to add the remaing element to the list
var final = data.concat(others);
console.log(final);
确实可以改进(添加支票,减少工作量),但我认为你有了这个想法。
答案 2 :(得分:1)
我的解决方案与GreenLeaf相似。它会创建一个新数组,而不是修改原始数据,这对您来说可能是也可能不是问题。
方法是首先删除克隆。然后,如果需要,可以对数组进行排序,然后最终将克隆插入其原始对象上方:
// create a new array without any clones, save the clones
var clonesMap = {};
var aWithoutClones = a.filter(function(item){
if (item.isClone) {
if (!clonesMap[item.originalId]) {
clonesMap[item.originalId] = [];
}
clonesMap[item.originalId].push(item);
return false;
}
return true;
});
// here you can sort aWithoutClones
// put all clones back before their original object
a = [];
for (var i = 0; i < aWithoutClones.length; i++) {
var currId = aWithoutClones[i].id;
if (clonesMap[currId]){
a = a.concat(clonesMap[currId]);
}
a.push(aWithoutClones[i]);
}
我认为这可以为您提供更大的灵活性,因为您现在有机会对数组进行排序而无需考虑克隆。此外,您还可以使用单独的排序功能对克隆进行排序。