按照另一个数组的顺序对一个数组进行排序

16
我有一些包含50多个名称的数组,就像这样。
["dan", "ryan", "bob", "steven", "corbin"]
["bob", "dan", "steven", "corbin"]

我有另一个数组,其中包含正确的顺序。请注意上面的第二个数组并不包括所有的名称,但我仍希望它遵循以下顺序:

["ryan", "corbin", "dan", "steven", "bob"]

这些数组没有逻辑顺序,只是按照这个顺序排列。对我来说有意义的是将每个数组与正确排序的数组进行比较。我想我看到一些人用 PHP 这样做,但我找不到 JavaScript 的解决方案。有没有人有什么想法如何做到这一点?我已经尝试了几个小时,但是无法解决。


你想以特定的顺序排列它们吗?如果你只是想让它们按照相同的顺序排列,那么你可以在这两个数组上使用.sort()方法。 - Aweary
5个回答

40

使用indexOf()获取参考数组中每个元素的位置,并在比较函数中使用。

var reference_array = ["ryan", "corbin", "dan", "steven", "bob"];
var array = ["bob", "dan", "steven", "corbin"];
array.sort(function(a, b) {
  return reference_array.indexOf(a) - reference_array.indexOf(b);
});
console.log(array); // ["corbin", "dan", "steven", "bob"]

对于大型数组,每次搜索引用数组都会效率低下,如果这是一个问题,您可以将其转换为将名称映射到位置的对象:

var reference_array = ["ryan", "corbin", "dan", "steven", "bob"];
reference_object = {};
for (var i = 0; i < reference_array.length; i++) {
    reference_object[reference_array[i]] = i;
}
var array = ["bob", "dan", "steven", "corbin"];
array.sort(function(a, b) {
  return reference_object[a] - reference_object[b];
});
console.log(array);


这个方法可以回答我提出的问题。我在没有说明我的原始数组实际上是一个对象的情况下提出了问题。为了解决这个问题,我能够使用_.keys从对象中获取键,然后使用您的方法reference_array.indexOf(a) - reference_array.indexOf(b)对它们进行排序。我用我的精确代码提出了第二个问题(http://stackoverflow.com/questions/28395477/javascript-sorting-parsed-json-within-each-loop),但最终我不得不弄清楚如何将对象转换为数组。我使用了这个答案和那个答案来最终解决我的排序问题。 - Barry
如果您有兴趣使用underscorejs库解决问题,那么请记得给您的问题打上标签。 - Barmar

1
你可以通过模式工厂函数实现一些排序器。然后使用你的模式创建排序器并将其应用于你的数组:
function sorterByPattern(pattern) {
    var hash = {};
    pattern.forEach(function(name, index) { hash[name] = index });

    return function(n1, n2) {
        if (!(n1 in hash)) return 1;  // checks if name is not in the pattern
        if (!(n2 in hash)) return -1; // if true - place that names to the end
        return hash[n1] - hash[n2];
    }
}

var sorter = sorterByPattern(["ryan", "corbin", "dan", "steven", "bob"]);

var arrays = [
    ["dan", "ryan", "bob", "steven", "corbin"],
    ["bob", "dan", "steven", "corbin"]
    /* ... */
];

arrays.forEach(function(array) { array.sort(sorter) });

1

我现在遇到了同样的问题,不过我尝试了一种略微不同的方法。它并不对数组进行排序,而是根据排序列表来过滤顺序列表,因此它有一些限制,但对于我的需求来说更好,因为它可以从排序列表中清除不正确的值:

  • 如果排序列表有重复的值,在排序后的列表中只会出现一次
  • 如果排序列表中有未包含在顺序列表中的项目,则不会出现在排序后的列表中

function sortOrder(getOrder,getArr){
  return getOrder.filter(function(order){
    return getArr.some(function(list){
      return order === list;
    });
  });
}

//arrays
var order = ["ryan", "corbin", "dan", "steven", "bob"];
var arA = ["dan", "ryan", "bob", "steven", "corbin"];
var arB = ["bob", "dan", "steven", "corbin"];
var arC = ["bob","ryan"];
var arD = ["bob","bob","corbin"]; //remove repetition
var arE = ["unrecognizedItem","corbin","steven","ryan"]; //remove the item not included in order array

//print results
document.body.innerHTML = sortOrder(order,arA)+'<br/>';
document.body.innerHTML += sortOrder(order,arB)+'<br/>';
document.body.innerHTML += sortOrder(order,arC)+'<br/>';
document.body.innerHTML += sortOrder(order,arD)+'<br/>';
document.body.innerHTML += sortOrder(order,arE)+'<br/>';


0
如果您需要按照循环顺序放置数组的值,例如:
输入:[1, 2, 4, 4, 3, 3, 2, 1]
输出:[1, 2, 3, 4, 1, 2, 3, 4]

那么您可以使用下面的两个函数。第一个函数使用第二个函数。
对于第一个函数,您需要提供两个参数:
第一个参数:您要排序的项目数组(上面的输入
第二个参数:正确顺序的数组(例如上面的[1, 2, 3, 4]

function sortByOrder (array, order) {

    const arrayOfArrays = order.map(v => {

        return [...Array(howMany(v, array))].map(undef => v);
    });

    const tempArray = [];

    arrayOfArrays.forEach((subArr, i) => {

        let index = order.indexOf(order[i]);

        subArr.forEach(duplicate => {

            tempArray[index] = duplicate;

            index += order.length;
        });
    });

    return tempArray.filter(v => v);
}

function howMany(value, array) {

        const regExp = new RegExp(value, 'g');

        return (array.join(' ').match(regExp) || []).length;
}

0
var a = ["Senior", "Junior", "Intern", "Office Assistant"];
var b = ["Junior", "Cleaner", "Senior", "Intern", "Office Assistant"];

var res = [];

for (var i = 0; i < a.length; i++) {
  for (var j = 0; j < b.length; j++) {
    if (a[i] == b[j]) {
      res.push(b[j]);
      b.splice(b.indexOf(b[j]), 1)
      break;
    }
  }
}

console.log(res.concat(b)); // [ 'Senior', 'Junior', 'Intern', 'Office Assistant', 'Cleaner' ]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接