簡體   English   中英

在Javascript中使用特定異常對對象數組進行排序

[英]Sorting an array of objects with specific exceptions in Javascript

我有一個對象數組,其中一些元素是另一個元素的克隆,因此它們有一個屬性引用原始的另一個屬性(簡化示例):

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;
});

對此有任何幫助將不勝感激,謝謝。

您應該使用以下排序功能:

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;
        }
    }
);

此處提供了功能工作的示例。

  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; } }); 
  2. 對它們進行排序,使它們全部打包在一起

     data.sort(function(a, b) { return a.originalID.localeCompare(b.originalID); //compare string }); 

您現在將所有具有相同originalID的元素打包在一起。 然后我們只需要在每個打包元素的末尾添加具有相同originalID的良好id的元素。

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);

它確實可以改進(添加支票,減少工作量),但我認為你有了這個想法。

我的解決方案與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]);
}

我認為這為您提供了更大的靈活性,因為您現在有機會對數組進行排序而無需考慮克隆。 此外,您還可以使用單獨的排序功能對克隆進行排序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM