Javascript - 基于_id的排序数组对Javascript对象进行排序的更快,更有效的方法?

时间:2015-08-07 07:01:51

标签: javascript arrays sorting javascript-objects

我们有MongoDB文档,如下所示:

VelocityEngineFactory

根据var JavascriptObject = { DbDocs : [ { _id : "1", {..more values..} }, { _id : "2", {..more values..} }, { _id : "3", {..more values..} } ] } 中的某些值,我们从文档中订购了一个_id数组,结果如下:

JavascriptObject

现在,我们通过将var OrderedArray = [ 2, 1, 3 ]; 中的_id与JavascriptObject中的_id匹配来重建整个OrderedArray

DbDocs

基于此var JavascriptObjectToRebuild = []; var DbDocuments = JavascriptObject.DbDocs; var DocumentCount = 0; for (var OrderedNumber in OrderedArray) { for (var Document in DbDocuments) { if ( DbDocuments[Document]._id === OrderedArray[OrderedNumber] ) { JavascriptObjectToRebuild[DocumentCount] = {}; // new Document Object JavascriptObjectToRebuild[DocumentCount]._id = DbDocuments[Document]._id; JavascriptObjectToRebuild[DocumentCount]...more values = DbDocuments[Document]...more values; DocumentCount++; // increment } } } var SortedJavascriptObject = { DbDocs: [] }; // format for client-side templating for (var Document in JSONToRebuild) { SortedJavascriptObject.DbDocs.push(JavascriptObjectToRebuild[Document]); } ,是否有更快捷有效的方式对JavascriptObject进行排序?

3 个答案:

答案 0 :(得分:3)

请参阅下面的更新,如果无法直接排序,则必须使用OrderedArray

如果您可以在Array#sort函数的回调中应用您的条件(例如,如果您可以通过将数组中的两个条目相互比较来实现),则可以直接对JSON.DbDocs进行排序

以下是根据_id的数值进行排序的示例;你自然会用比较对象的逻辑来代替它。

另请注意我已经更改了顶级变量的名称(JSON有点使用,无论如何,它不是JSON):

var Obj = {
  DbDocs : [
    {
      _id : "2",
      more: "two"
    },
    {
      _id : "1",
      more: "one"
    },
    {
      _id : "3",
       more: "three"
    }
  ]
};
Obj.DbDocs.sort(function(a, b) {
  return +a._id - +b._id; // Replace with your logic comparing a and b
});
document.querySelector('pre').innerHTML = JSON.stringify(Obj, null, 2);
<pre></pre>

如果无法直接排序并且 可以使用OrderedArray工作,那么sort仍然可以使用,但它不太优雅:您使用{{1}找出数组中每个条目的位置:

Array#indexOf

Obj.DbDocs.sort(function(a, b) { return OrderedArray.indexOf(+a._id) - OrderedArray.indexOf(+b._id); }); 将ID从字符串转换为数字,因为+包含问题中的数字,但ID值是字符串。)

直播示例:

OrderedArray
var Obj = {
  DbDocs : [
    {
      _id : "1",
      more: "one"
    },
    {
      _id : "2",
      more: "two"
    },
    {
      _id : "3",
       more: "three"
    }
  ]
};
var OrderedArray = [2, 1, 3];
Obj.DbDocs.sort(function(a, b) {
  return OrderedArray.indexOf(+a._id) - OrderedArray.indexOf(+b._id);
});
document.querySelector('pre').innerHTML = JSON.stringify(Obj, null, 2);

如果<pre></pre>中有大量条目,您可能需要先创建一个查找对象,以避免大量OrderedArray次调用(代价高昂:({{ 3}}在答案中做到了这一点,但他因为某种原因将其删除了)

indexOf

(我们不需要将ID转换为数字,因为属性名称始终是字符串,因此我们在构建地图时将数字转换为字符串。)

直播示例:

var OrderMap = {}
OrderedArray.forEach(function(entry, index) {
  OrderMap[entry] = index;
});
Obj.DbDocs.sort(function(a, b) {
  return OrderMap[a._id] - OrderMap[b._id];
});
var Obj = {
  DbDocs : [
    {
      _id : "1",
      more: "one"
    },
    {
      _id : "2",
      more: "two"
    },
    {
      _id : "3",
       more: "three"
    }
  ]
};
var OrderedArray = [2, 1, 3];
var OrderMap = {}
OrderedArray.forEach(function(entry, index) {
  OrderMap[entry] = index;
});
Obj.DbDocs.sort(function(a, b) {
  return OrderMap[a._id] - OrderMap[b._id];
});
document.querySelector('pre').innerHTML = JSON.stringify(Obj, null, 2);

答案 1 :(得分:1)

303见other

...

OrderedNumber转换为哈希_id => position

sorter = {}
OrderedNumber.forEach(function(_id, pos) {
    sorter[_id] = pos
})

然后通过比较id的位置对目标数组进行排序:

DbDocuments.sort(function(a, b) {
    return sorter[a._id] - sorter[b._id];
})

答案 2 :(得分:1)

据我所知,你想得到这样的结果,

[{"_id":"2"}, {"_id":"1"}, {"_id":"3"}]

所以你可以使用一个forEachindexOf,就像这样

&#13;
&#13;
var JSONDADA = {
    DbDocs : [{_id : "1",}, {_id : "2"}, {_id : "3"}]
};

var DbDocuments = JSONDADA.DbDocs;
var OrderedArray = [ 2, 1, 3 ];
var result = [];

DbDocuments.forEach(function (el) {
    var position = OrderedArray.indexOf(+el._id);
    
    if (position >= 0) {
        result[position] = el;
    }
});
console.log(JSON.stringify(result));
&#13;
&#13;
&#13;