当前位置: 代码迷 >> JavaScript >> Javascript - 基于_id的排序数组对Javascript对象进行排序的更快,更有效的方法?
  详细解决方案

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

热度:65   发布时间:2023-06-06 08:54:51.0

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

var JavascriptObject = {
  DbDocs : [
    {
      _id : "1",
      {..more values..}
    },
    {
      _id : "2",
      {..more values..}
    },
    {
      _id : "3",
      {..more values..}
    }
  ]
}

基于JavascriptObject中的某些值,我们从文档中订购了一个_id数组,结果如下:

var OrderedArray = [ 2, 1, 3 ];

现在,我们正在重建整个JavascriptObject由该_id匹配OrderedArray与在_id 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]);
}

是否有更快更有效的方法来基于此OrderedArrayJavascriptObject进行排序?

如果无法直接排序而您必须使用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 ,但它不太优雅:使用Array#indexOf来找出数组中每个条目的位置:

Obj.DbDocs.sort(function(a, b) {
  return OrderedArray.indexOf(+a._id) - OrderedArray.indexOf(+b._id);
});

+将ID从字符串转换为数字,因为OrderedArray在您的问题中包含数字,但ID值是字符串。)

实例:

 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有很多条目,你可能想先创建一个查找对象,以避免大量的indexOf调用(代价( 在答案中做到了这一点,但他因为某些原因删除了它)

var OrderMap = {}
OrderedArray.forEach(function(entry, index) {
  OrderMap[entry] = index;
});
Obj.DbDocs.sort(function(a, b) {
  return OrderMap[a._id] - OrderMap[b._id];
});

(我们不需要将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); 
 <pre></pre> 

303见

......

OrderedNumber转换为hash _id => position

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

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

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

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

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

所以你可以使用一个forEachindexOf来完成它,就像这样

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

  相关解决方案