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

时间:2022-01-31 13:03:09

For example, if I have these arrays:

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

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

And I use name.sort() the order of the "name" array becomes:

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

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

But, how can I sort the "name" array and have the "age" array keep the same order? Like this:

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

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

8 个解决方案

#1


43  

You can sort the existing arrays, or reorganize the data.

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

Method 1: To use the existing arrays, you can combine, sort, and separate them: (Assuming equal length arrays)

方法1:要使用现有数组,您可以组合,排序和分离它们:(假设等长数组)

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

This has the advantage of not relying on string parsing techniques, and could be used on any number of arrays that need to be sorted together.

这样做的好处是不依赖于字符串解析技术,并且可以在需要一起排序的任意数量的数组上使用。

Method 2: Or you can reorganize the data a bit, and just sort a collection of objects:

方法2:或者您可以稍微重新组织数据,只需对对象集合进行排序:

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

For the comparisons,-1 means lower index, 0 means equal, and 1 means higher index. And it is worth noting that sort() actually changes the underlying array.

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

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

#2


2  

You are trying to sort 2 independet arrays by only calling sort() on one of them.

您只是在其中一个上调用sort()来尝试对2个独立数组进行排序。

One way of achieving this would be writing your own sorting methd which would take care of this, meaning when it swaps 2 elements in-place in the "original" array, it should swap 2 elements in-place in the "attribute" array.

实现这一目标的一种方法是编写自己的排序方法,这将解决这个问题,这意味着当它在“原始”数组中就地交换2个元素时,它应该在“属性”数组中就地交换2个元素。

Here is a pseudocode on how you might try it.

这是一个关于如何尝试它的伪代码。

function mySort(originals, attributes) {
    // Start of your sorting code here
        swap(originals, i, j);
        swap(attributes, i, j);
    // Rest of your sorting code here
}

#3


2  

I was having the same issue and came up with this incredibly simple solution. First combine the associated ellements into strings in a seperate array then use parseInt in your sort comparison function like this:

我遇到了同样的问题,想出了这个非常简单的解决方案。首先将关联的元素组合成一个单独的数组中的字符串,然后在排序比较函数中使用parseInt,如下所示:

<html>
<body>
<div id="outPut"></div>
<script>
var theNums = [13,12,14];
var theStrs = ["a","b","c"];
var theCombine = [];

for (var x in theNums)
{
    theCombine[x] = theNums[x] + "," + theStrs;
}

var theSorted = theAr.sort(function(a,b)
{
    var c = parseInt(a,10);
    var d = parseInt(b,10);
    return c-d;
});
document.getElementById("outPut").innerHTML = theS;
</script>
</body>
</html>

#4


1  

inspired from @jwatts1980's answer, and @Alexander's answer here I merged both answer's into a quick and dirty solution; The main array is the one to be sorted, the rest just follows its indexes

灵感来自@ jwatts1980的回答,@ Alexander的答案在这里我将两个答案合并为一个快速而肮脏的解决方案;主数组是要排序的数组,其余数组只跟随其索引

NOTE: Not very efficient for very very large arrays

注意:对于非常大的阵列来说效率不高

 /* @sort argument is the array that has the values to sort
   @followers argument is an array of arrays which are all same length of 'sort'
   all will be sorted accordingly
   example:

   sortMutipleArrays(
         [0, 6, 7, 8, 3, 4, 9], 
         [ ["zr", "sx", "sv", "et", "th", "fr", "nn"], 
           ["zero", "six", "seven", "eight", "three", "four", "nine"] 
         ]
   );

  // Will return

  {  
     sorted: [0, 3, 4, 6, 7, 8, 9], 
     followed: [
      ["zr", th, "fr", "sx", "sv", "et", "nn"], 
      ["zero", "three", "four", "six", "seven", "eight", "nine"]
     ]
   }
 */

You probably want to change the method signature/return structure, but that should be easy though. I did it this way because I needed it

您可能想要更改方法签名/返回结构,但这应该很容易。我是这样做的,因为我需要它

var sortMultipleArrays = function (sort, followers) {
  var index = this.getSortedIndex(sort)
    , followed = [];
  followers.unshift(sort);
  followers.forEach(function(arr){
    var _arr = [];
    for(var i = 0; i < arr.length; i++)
      _arr[i] = arr[index[i]];
    followed.push(_arr);
  });
  var result =  {sorted: followed[0]};
  followed.shift();
  result.followed = followed;
  return result;
};

var getSortedIndex = function (arr) {
  var index = [];
  for (var i = 0; i < arr.length; i++) {
    index.push(i);
  }
  index = index.sort((function(arr){
  /* this will sort ints in descending order, change it based on your needs */
    return function (a, b) {return ((arr[a] > arr[b]) ? -1 : ((arr[a] < arr[b]) ? 1 : 0));
    };
  })(arr));
  return index;
};

#5


1  

It is very similar to jwatts1980's answer (Update 2). Consider reading Sorting with map.

它与jwatts1980的答案(Update 2)非常相似。考虑阅读使用地图排序。

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

#6


1  

I was looking for something more generic and functional than the current answers.

我正在寻找比当前答案更通用和更实用的东西。

Here's what I came up with: an es6 implementation (with no mutations!) that lets you sort as many arrays as you want given a "source" array

这就是我想出的:一个es6实现(没有突变!),它允许您根据需要对“源”数组进行排序

/**
 * Given multiple arrays of the same length, sort one (the "source" array), and
 * sort all other arrays to reorder the same way the source array does.
 * 
 * Usage:
 * 
 * sortMultipleArrays( objectWithArrays, sortFunctionToApplyToSource )
 * 
 * sortMultipleArrays(
 *   {
 *    source: [...],
 *    other1: [...],
 *    other2: [...]
 *   },
 *   (a, b) => { return a - b })
 * )
 * 
 * Returns:
 *   {
 *      source: [..sorted source array]
 *      other1: [...other1 sorted in same order as source],
 *      other2: [...other2 sorted in same order as source]
 *   }
 */
export function sortMultipleArrays( namedArrays, sortFn ) {
    const { source } = namedArrays;
    if( !source ) {
        throw new Error('You must pass in an object containing a key named "source" pointing to an array');
    }

    const arrayNames = Object.keys( namedArrays );

    // First build an array combining all arrays into one, eg
    // [{ source: 'source1', other: 'other1' }, { source: 'source2', other: 'other2' } ...]
    return source.map(( value, index ) =>
        arrayNames.reduce((memo, name) => ({
            ...memo,
            [ name ]: namedArrays[ name ][ index ]
        }), {})
    )
    // Then have user defined sort function sort the single array, but only
    // pass in the source value
    .sort(( a, b ) => sortFn( a.source, b.source ))
    // Then turn the source array back into an object with the values being the
    // sorted arrays, eg
    // { source: [ 'source1', 'source2' ], other: [ 'other1', 'other2' ] ... }
    .reduce(( memo, group ) =>
        arrayNames.reduce((ongoingMemo, arrayName) => ({
            ...ongoingMemo,
            [ arrayName ]: [
                ...( ongoingMemo[ arrayName ] || [] ),
                group[ arrayName ]
            ]
        }), memo), {});
}

#7


0  

You could append the original index of each member to the value, sort the array, then remove the index and use it to re-order the other array. It will only work where the contents are strings or can be converted to and from strings successfuly.

您可以将每个成员的原始索引附加到值,对数组进行排序,然后删除索引并使用它来重新排序其他数组。它只能在内容为字符串的情况下工作,或者可以成功地转换为字符串和从字符串转换。

Another solution is keep a copy of the original array, then after sorting, find where each member is now and adjust the other array appropriately.

另一个解决方案是保留原始数组的副本,然后在排序后,找到每个成员现在的位置并适当调整另一个数组。

#8


0  

Simplest explantion is the best, merge the arrays, and then extract after sorting: create an array

最简单的解释是最好的,合并数组,然后在排序后提取:创建一个数组

name_age=["bob@10","Tom@20","Larry@30"];

sort the array as before, then extract the name and the age, you can use @ to reconise where name ends and age begins. Maybe not a method for the purist, but I have the same issue and this my approach.

像以前一样对数组进行排序,然后提取名称和年龄,您可以使用@来重新确定名称结束和年龄开始的位置。也许不是纯粹主义者的方法,但我有同样的问题和我的方法。

#1


43  

You can sort the existing arrays, or reorganize the data.

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

Method 1: To use the existing arrays, you can combine, sort, and separate them: (Assuming equal length arrays)

方法1:要使用现有数组,您可以组合,排序和分离它们:(假设等长数组)

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

This has the advantage of not relying on string parsing techniques, and could be used on any number of arrays that need to be sorted together.

这样做的好处是不依赖于字符串解析技术,并且可以在需要一起排序的任意数量的数组上使用。

Method 2: Or you can reorganize the data a bit, and just sort a collection of objects:

方法2:或者您可以稍微重新组织数据,只需对对象集合进行排序:

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

For the comparisons,-1 means lower index, 0 means equal, and 1 means higher index. And it is worth noting that sort() actually changes the underlying array.

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

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

#2


2  

You are trying to sort 2 independet arrays by only calling sort() on one of them.

您只是在其中一个上调用sort()来尝试对2个独立数组进行排序。

One way of achieving this would be writing your own sorting methd which would take care of this, meaning when it swaps 2 elements in-place in the "original" array, it should swap 2 elements in-place in the "attribute" array.

实现这一目标的一种方法是编写自己的排序方法,这将解决这个问题,这意味着当它在“原始”数组中就地交换2个元素时,它应该在“属性”数组中就地交换2个元素。

Here is a pseudocode on how you might try it.

这是一个关于如何尝试它的伪代码。

function mySort(originals, attributes) {
    // Start of your sorting code here
        swap(originals, i, j);
        swap(attributes, i, j);
    // Rest of your sorting code here
}

#3


2  

I was having the same issue and came up with this incredibly simple solution. First combine the associated ellements into strings in a seperate array then use parseInt in your sort comparison function like this:

我遇到了同样的问题,想出了这个非常简单的解决方案。首先将关联的元素组合成一个单独的数组中的字符串,然后在排序比较函数中使用parseInt,如下所示:

<html>
<body>
<div id="outPut"></div>
<script>
var theNums = [13,12,14];
var theStrs = ["a","b","c"];
var theCombine = [];

for (var x in theNums)
{
    theCombine[x] = theNums[x] + "," + theStrs;
}

var theSorted = theAr.sort(function(a,b)
{
    var c = parseInt(a,10);
    var d = parseInt(b,10);
    return c-d;
});
document.getElementById("outPut").innerHTML = theS;
</script>
</body>
</html>

#4


1  

inspired from @jwatts1980's answer, and @Alexander's answer here I merged both answer's into a quick and dirty solution; The main array is the one to be sorted, the rest just follows its indexes

灵感来自@ jwatts1980的回答,@ Alexander的答案在这里我将两个答案合并为一个快速而肮脏的解决方案;主数组是要排序的数组,其余数组只跟随其索引

NOTE: Not very efficient for very very large arrays

注意:对于非常大的阵列来说效率不高

 /* @sort argument is the array that has the values to sort
   @followers argument is an array of arrays which are all same length of 'sort'
   all will be sorted accordingly
   example:

   sortMutipleArrays(
         [0, 6, 7, 8, 3, 4, 9], 
         [ ["zr", "sx", "sv", "et", "th", "fr", "nn"], 
           ["zero", "six", "seven", "eight", "three", "four", "nine"] 
         ]
   );

  // Will return

  {  
     sorted: [0, 3, 4, 6, 7, 8, 9], 
     followed: [
      ["zr", th, "fr", "sx", "sv", "et", "nn"], 
      ["zero", "three", "four", "six", "seven", "eight", "nine"]
     ]
   }
 */

You probably want to change the method signature/return structure, but that should be easy though. I did it this way because I needed it

您可能想要更改方法签名/返回结构,但这应该很容易。我是这样做的,因为我需要它

var sortMultipleArrays = function (sort, followers) {
  var index = this.getSortedIndex(sort)
    , followed = [];
  followers.unshift(sort);
  followers.forEach(function(arr){
    var _arr = [];
    for(var i = 0; i < arr.length; i++)
      _arr[i] = arr[index[i]];
    followed.push(_arr);
  });
  var result =  {sorted: followed[0]};
  followed.shift();
  result.followed = followed;
  return result;
};

var getSortedIndex = function (arr) {
  var index = [];
  for (var i = 0; i < arr.length; i++) {
    index.push(i);
  }
  index = index.sort((function(arr){
  /* this will sort ints in descending order, change it based on your needs */
    return function (a, b) {return ((arr[a] > arr[b]) ? -1 : ((arr[a] < arr[b]) ? 1 : 0));
    };
  })(arr));
  return index;
};

#5


1  

It is very similar to jwatts1980's answer (Update 2). Consider reading Sorting with map.

它与jwatts1980的答案(Update 2)非常相似。考虑阅读使用地图排序。

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

#6


1  

I was looking for something more generic and functional than the current answers.

我正在寻找比当前答案更通用和更实用的东西。

Here's what I came up with: an es6 implementation (with no mutations!) that lets you sort as many arrays as you want given a "source" array

这就是我想出的:一个es6实现(没有突变!),它允许您根据需要对“源”数组进行排序

/**
 * Given multiple arrays of the same length, sort one (the "source" array), and
 * sort all other arrays to reorder the same way the source array does.
 * 
 * Usage:
 * 
 * sortMultipleArrays( objectWithArrays, sortFunctionToApplyToSource )
 * 
 * sortMultipleArrays(
 *   {
 *    source: [...],
 *    other1: [...],
 *    other2: [...]
 *   },
 *   (a, b) => { return a - b })
 * )
 * 
 * Returns:
 *   {
 *      source: [..sorted source array]
 *      other1: [...other1 sorted in same order as source],
 *      other2: [...other2 sorted in same order as source]
 *   }
 */
export function sortMultipleArrays( namedArrays, sortFn ) {
    const { source } = namedArrays;
    if( !source ) {
        throw new Error('You must pass in an object containing a key named "source" pointing to an array');
    }

    const arrayNames = Object.keys( namedArrays );

    // First build an array combining all arrays into one, eg
    // [{ source: 'source1', other: 'other1' }, { source: 'source2', other: 'other2' } ...]
    return source.map(( value, index ) =>
        arrayNames.reduce((memo, name) => ({
            ...memo,
            [ name ]: namedArrays[ name ][ index ]
        }), {})
    )
    // Then have user defined sort function sort the single array, but only
    // pass in the source value
    .sort(( a, b ) => sortFn( a.source, b.source ))
    // Then turn the source array back into an object with the values being the
    // sorted arrays, eg
    // { source: [ 'source1', 'source2' ], other: [ 'other1', 'other2' ] ... }
    .reduce(( memo, group ) =>
        arrayNames.reduce((ongoingMemo, arrayName) => ({
            ...ongoingMemo,
            [ arrayName ]: [
                ...( ongoingMemo[ arrayName ] || [] ),
                group[ arrayName ]
            ]
        }), memo), {});
}

#7


0  

You could append the original index of each member to the value, sort the array, then remove the index and use it to re-order the other array. It will only work where the contents are strings or can be converted to and from strings successfuly.

您可以将每个成员的原始索引附加到值,对数组进行排序,然后删除索引并使用它来重新排序其他数组。它只能在内容为字符串的情况下工作,或者可以成功地转换为字符串和从字符串转换。

Another solution is keep a copy of the original array, then after sorting, find where each member is now and adjust the other array appropriately.

另一个解决方案是保留原始数组的副本,然后在排序后,找到每个成员现在的位置并适当调整另一个数组。

#8


0  

Simplest explantion is the best, merge the arrays, and then extract after sorting: create an array

最简单的解释是最好的,合并数组,然后在排序后提取:创建一个数组

name_age=["bob@10","Tom@20","Larry@30"];

sort the array as before, then extract the name and the age, you can use @ to reconise where name ends and age begins. Maybe not a method for the purist, but I have the same issue and this my approach.

像以前一样对数组进行排序,然后提取名称和年龄,您可以使用@来重新确定名称结束和年龄开始的位置。也许不是纯粹主义者的方法,但我有同样的问题和我的方法。