我们有如下所示的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]);
}

是否有基于此JavascriptObject排序OrderedArray的更快,更有效的方法?

最佳答案

如果无法直接排序,而必须使用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调用(这很昂贵:( georg在回答中做到了这一点,但由于某种原因他已将其删除))
var OrderMap = {}
OrderedArray.forEach(function(entry, index) {
  OrderMap[entry] = index;
});
Obj.DbDocs.sort(function(a, b) {
  return OrderMap[a._id] - OrderMap[b._id];
});

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

实时示例:

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>

09-10 15:38
查看更多