【问题标题】:Sorting an array of objects with specific exceptions in Javascript在Javascript中对具有特定异常的对象数组进行排序
【发布时间】:2015-03-20 11:27:24
【问题描述】:

我有一个对象数组,其中一些元素是另一个元素的克隆,因此它们有一个引用原始属性的另一个属性的属性(简化示例):

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

非常感谢您对此的任何帮助,谢谢。

【问题讨论】:

  • 所以您不希望该数组中原始项目的顺序发生变化?然后我认为“排序”不是要走的路(因为当你“排序”整个数组时你将很难保持这个顺序),而是构建一个新数组。
  • 您还需要将one.originalIdother.id 进行比较。
  • 那么您希望按什么对原件进行排序?
  • 返回1怎么样?通常负数 (-1) 浮动到顶部,正数 (+1) 下沉到底部,并且相同 (0) 在排序时保持原位。
  • 一个对象可以有多少个克隆?

标签: javascript arrays algorithm sorting


【解决方案1】:

您应该使用以下排序功能:

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 以获得正确的解决方案,但解释会很好。请注意,您还应该return 0 for identical values
  • 不幸的是,我相信这种字符串比较不会起作用,因为不能保证 ids/originalIds 是按时间顺序排列的……对吧?不过,让我更深入地了解了您可以使用排序功能做什么,非常感谢!
  • @AndreasBohman:嗯,你想按 id 排序,不是吗?
【解决方案2】:

我的解决方案类似于 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]);
}

我认为这为您提供了更大的灵活性,因为您现在有机会对数组进行排序而无需考虑克隆。此外,您还可以使用单独的排序功能对克隆进行排序。

【讨论】:

  • 完美,可以解决问题,对我来说是最理想的,因为它允许我只保存克隆以方便以后使用。非常感谢!
【解决方案3】:
  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);

当然可以改进(添加检查,做更少的工作),但我想你明白了。

【讨论】:

    猜你喜欢
    • 2018-10-10
    • 2019-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-25
    • 2012-05-02
    相关资源
    最近更新 更多