Javascript 按另一个数组对集合排序

Javascript 按另一个数组对集合排序,javascript,underscore.js,Javascript,Underscore.js,我有一系列的名字: [ {last_name: "A", name: "James" }, {last_name: "A", name: "Robert" }, {last_name: "B", name: "Tim"}, {last_name: "B", name: "Bob" }, {last_name: "C", name: "Ricky Ticky" } ] 然后我有一个数组,其中每个姓氏,按特定顺序排列: ["B", "C", "A"] 如何按照第二个数组

我有一系列的名字:

[
  {last_name: "A", name: "James" }, 
  {last_name: "A", name: "Robert" }, 
  {last_name: "B", name: "Tim"}, 
  {last_name: "B", name: "Bob" },
  {last_name: "C", name: "Ricky Ticky" }
]
然后我有一个数组,其中每个
姓氏
,按特定顺序排列:

["B", "C", "A"]
如何按照第二个数组中姓氏的顺序对集合进行排序

我所尝试的:


到目前为止,我拥有的最佳解决方案是创建一个新数组,然后循环我的名称集合,推送与排序数组的第一个索引(“B”),然后是第二个索引(“C”),最后是“a”匹配的所有元素。似乎冗长,或者下划线.js有更好的方法。

使用下划线的
sortBy
函数,可以根据数组元素的任意特性进行排序:

var-people=[
{姓:“A”,名:“詹姆斯”},
{姓:“A”,名:“罗伯特”},
{姓:“B”,姓:“Tim”},
{姓:“B”,姓:“鲍勃”},
{姓:“C”,名:“里奇·蒂奇”}
];
var lastNameOrder=[“B”、“C”、“A”];
var sortedPeople=u.sortBy(人员,功能(人员){
返回lastNameOrder.indexOf(person.last_name);
})
控制台日志(分类人员)

使用Array.sort()可以相当简单地完成此操作

Array.prototype.sort()将通过一次比较两个值对数组进行排序。如果返回1,则b在a之前-1、a在b之前;零是不变的


有关详细信息,请访问编辑的

:由于严重故障

但它仍然没有对名字进行排序,因为我看不出有任何理由不这样做

var people = [
  {last_name: "A", name: "James" }, 
  {last_name: "A", name: "Robert" }, 
  {last_name: "B", name: "Tim"}, 
  {last_name: "B", name: "Bob" },
  {last_name: "C", name: "Ricky Ticky" }
];

var lastNameOrder = ["B", "C", "A"];

var sortedPeople = people.sort(function(person1,person2){
  var lna =  lastNameOrder.indexOf(person1.last_name);
  var lnb =  lastNameOrder.indexOf(person2.last_name);

  if(lna === lnb){
    return (person1.name < person2.name) ? -1 : 
           (person1.name > person2.name) ?  1 : 0;
  } else {
    return lna-lnb;
  }
})
var-people=[
{姓:“A”,名:“詹姆斯”},
{姓:“A”,名:“罗伯特”},
{姓:“B”,姓:“Tim”},
{姓:“B”,姓:“鲍勃”},
{姓:“C”,名:“里奇·蒂奇”}
];
var lastNameOrder=[“B”、“C”、“A”];
var sortedPeople=people.sort(函数(person1,person2){
var lna=lastNameOrder.indexOf(person1.last_name);
var lnb=lastNameOrder.indexOf(person2.last_name);
如果(lna==lnb){
返回(person1.nameperson2.name)?1:0;
}否则{
返回lna lnb;
}
})

dig the raw JS-现在就尝试这比下划线的实现慢,因为它在每次比较时调用
indexOf
(可能是
O(n log(n))
),下划线在每个元素中调用它一次(
O(n)
)。挖掘算法分析-在我的情况下,速度无关紧要(小数组),但是很高兴知道为什么你的比较器函数从不返回负值?@BradyCartmell如果不返回负值,它肯定会在某些数据集上失败。JS需要一个比较器函数<代码>排序(函数(元素){…})
不正确。如果你得到了正确的结果,那就是巧合;用不同的
lastNameOrder
试试。是的,没错,我没有完全测试它。甚至我的第二个例子也有错误!您还可以在
lastNameOrder
上进行一次遍历,以在
对象中构建名称->索引映射,然后在
函数中使用该
对象。对于如此小的数据集,可能会更快,可能不会,甚至可能不会引起注意。@muistooshort:这正是
\uu.sortBy
所做的-我会重复它的工作。(这也是我第一次评论布雷迪实施计划的原因。)不完全是。
sortBy
所做的施瓦茨变换最终将调用
indexOf
people.length
次。如果你手工构建名称->索引映射,你根本不会调用
indexOf
,你只需通过
lastNameOrder
而不是
people.length
线性搜索;你最终会做
people.length
查找name->index对象,而不是所有那些
indexOf
调用。@muistooshort:哦,我明白你现在说的了。
var people = [
  {last_name: "A", name: "James" }, 
  {last_name: "A", name: "Robert" }, 
  {last_name: "B", name: "Tim"}, 
  {last_name: "B", name: "Bob" },
  {last_name: "C", name: "Ricky Ticky" }
];

var lastNameOrder = ["B", "C", "A"];

var sortedPeople = people.sort(function(person1,person2){
  var lna =  lastNameOrder.indexOf(person1.last_name);
  var lnb =  lastNameOrder.indexOf(person2.last_name);

  if(lna === lnb){
    return (person1.name < person2.name) ? -1 : 
           (person1.name > person2.name) ?  1 : 0;
  } else {
    return lna-lnb;
  }
})