以相同的方式对两个数组进行排序

IT技术 javascript
2021-01-24 02:17:38

例如,如果我有这些数组:

var name = ["Bob","Tom","Larry"];
var age =  ["10", "20", "30"];

我使用name.sort()“名称”数组的顺序变为:

var name = ["Bob","Larry","Tom"];

但是,如何对“name”数组进行排序并使“age”数组保持相同的顺序?像这样:

var name = ["Bob","Larry","Tom"];
var age =  ["10", "30", "20"];
6个回答

您可以对现有数组进行排序,或重新组织数据。

方法一: 使用已有的数组,可以对它们进行组合、排序、分离:( 假设数组长度相等)

var names = ["Bob","Tom","Larry"];
var ages =  ["10", "20", "30"];

//1) combine the arrays:
var list = [];
for (var j = 0; j < names.length; j++) 
    list.push({'name': names[j], 'age': ages[j]});

//2) sort:
list.sort(function(a, b) {
    return ((a.name < b.name) ? -1 : ((a.name == b.name) ? 0 : 1));
    //Sort could be modified to, for example, sort on the age 
    // if the name is the same.
});

//3) separate them back out:
for (var k = 0; k < list.length; k++) {
    names[k] = list[k].name;
    ages[k] = list[k].age;
}

这具有不依赖字符串解析技术的优点,并且可以用于需要一起排序的任意数量的数组。

方法二:或者你可以稍微重新组织一下数据,然后对一组对象进行排序:

var list = [
    {name: "Bob", age: 10}, 
    {name: "Tom", age: 20},
    {name: "Larry", age: 30}
    ];

list.sort(function(a, b) {
    return ((a.name < b.name) ? -1 : ((a.name == b.name) ? 0 : 1));
});

for (var i = 0; i<list.length; i++) {
    alert(list[i].name + ", " + list[i].age);
}
​

对于比较,-1 表示较低的索引,0 表示相等,1 表示较高的索引。值得注意的是,sort()实际上改变了底层数组。

同样值得注意的是,方法 2 更有效,因为除了排序之外,您不必两次遍历整个列表。

http://jsfiddle.net/ghBn7/38/

@TomášZato 并行排序两个数组在 JS 中不是原生的。这是一个非常简单的解决方案,但如果您找到一个更简单的解决方案,我很乐意看到它!:-)
2021-03-14 02:17:38
我总是忘记如何在 javascript 中做到这一点。服务器端脚本语言只是内置了这个......我猜太被宠坏了。
2021-03-15 02:17:38
很好的答案,正是我需要的。谢谢。这里排序基于 list.sort(function (a, b) { return parseInt(a.age) - parseInt(b.age) })
2021-04-08 02:17:38

此解决方案(我的工作)对多个数组进行排序,无需将数据转换为中间结构,并且可以高效地处理大型数组。它允许将数组作为列表或对象传递,并支持自定义 compareFunction。

用法:

let people = ["john", "benny", "sally", "george"];
let peopleIds = [10, 20, 30, 40];

sortArrays([people, peopleIds]);
[["benny", "george", "john", "sally"], [20, 40, 10, 30]] // output

sortArrays({people, peopleIds});
{"people": ["benny", "george", "john", "sally"], "peopleIds": [20, 40, 10, 30]} // output

算法:

  • 创建主数组的索引列表 (sortableArray)
  • 使用比较值的自定义 compareFunction 对索引进行排序,使用索引查找
  • 对于每个输入数组,按顺序将每个索引映射到其值

执行:

/**
 *  Sorts all arrays together with the first. Pass either a list of arrays, or a map. Any key is accepted.
 *     Array|Object arrays               [sortableArray, ...otherArrays]; {sortableArray: [], secondaryArray: [], ...}
 *     Function comparator(?,?) -> int   optional compareFunction, compatible with Array.sort(compareFunction)
 */
function sortArrays(arrays, comparator = (a, b) => (a < b) ? -1 : (a > b) ? 1 : 0) {
    let arrayKeys = Object.keys(arrays);
    let sortableArray = Object.values(arrays)[0];
    let indexes = Object.keys(sortableArray);
    let sortedIndexes = indexes.sort((a, b) => comparator(sortableArray[a], sortableArray[b]));

    let sortByIndexes = (array, sortedIndexes) => sortedIndexes.map(sortedIndex => array[sortedIndex]);

    if (Array.isArray(arrays)) {
        return arrayKeys.map(arrayIndex => sortByIndexes(arrays[arrayIndex], sortedIndexes));
    } else {
        let sortedArrays = {};
        arrayKeys.forEach((arrayKey) => {
            sortedArrays[arrayKey] = sortByIndexes(arrays[arrayKey], sortedIndexes);
        });
        return sortedArrays;
    }
}

另见https://gist.github.com/boukeversteegh/3219ffb912ac6ef7282b1f5ce7a379ad

嗨,复杂度是多少?(两者:时间和空间)
2021-03-16 02:17:38
对于 N 个数组,它将执行 N+1 次排序。通过不按索引对子数组进行排序,而是循环遍历每个子数组并使用 sortedIndexes 复制出正确的元素,可以将该算法优化为 [1 Sort + N loops]。我不知道 Object.values 和 Object.keys 是引用还是副本。我猜内存使用量将是输入数组的一些低倍数(在 2-4 之间)
2021-04-01 02:17:38

您可以name使用Array.from(name.keys())or获取数组的索引[...name.keys()]indices根据它们的值对它们进行排序然后用于map获取任意数量的相关数组中相应索引的值

const indices = Array.from(name.keys())
indices.sort( (a,b) => name[a].localeCompare(name[b]) )

const sortedName = indices.map(i => name[i]),
const sortedAge = indices.map(i => age[i])

这是一个片段:

如果性能很重要,则有用于该目的的sort-ids包:

var sortIds = require('sort-ids')
var reorder = require('array-rearrange')

var name = ["Bob","Larry","Tom"];
var age =  [30, 20, 10];

var ids = sortIds(age)
reorder(age, ids)
reorder(name, ids)

这比比较器功能快约 5 倍。

比什么“比较器函数”快?最快的是(a, b) => (a - b),比原生jsbench.github.io/#c90f8f13202ce5498f811ff79fb281ed快 6 倍.sort()
2021-04-12 02:17:38

它与jwatts1980's answer (Update 2)非常相似考虑阅读Sorting with map

name.map(function (v, i) {
    return {
        value1  : v,
        value2  : age[i]
    };
}).sort(function (a, b) {
    return ((a.value1 < b.value1) ? -1 : ((a.value1 == b.value1) ? 0 : 1));
}).forEach(function (v, i) {
    name[i] = v.value1;
    age[i] = v.value2;
});
对数组进行三次迭代并不理想。
2021-03-27 02:17:38