Сортируйте два массива одинаково
Например, если у меня есть эти массивы:
var name = ["Bob","Tom","Larry"];
var age = ["10", "20", "30"];
И я использую name.sort()
порядок массива "name":
var name = ["Bob","Larry","Tom"];
Но как я могу отсортировать массив "name" и иметь массив "age", сохраняющий один и тот же порядок? Вот так:
var name = ["Bob","Larry","Tom"];
var age = ["10", "30", "20"];
Ответы
Ответ 1
Вы можете отсортировать существующие массивы или реорганизовать данные.
Метод 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;
}
Это имеет то преимущество, что не полагается на методы синтаксического анализа строк и может использоваться для любого количества массивов, которые необходимо сортировать вместе.
Способ 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);
}
Для сравнений -1 означает более низкий индекс, 0 означает равный, а 1 означает более высокий индекс. И стоит отметить, что sort()
фактически изменяет базовый массив.
http://jsfiddle.net/ghBn7/38/
Ответ 2
Он очень похож на jwatts1980 answer (обновление 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;
});
Ответ 3
Вы пытаетесь сортировать 2 независимых массива, только вызывая sort() на одном из них.
Одним из способов достижения этого было бы написать свой собственный метод сортировки, который позаботился об этом, а это значит, что когда он заменяет 2 элемента на месте в "исходном" массиве, он должен заменить 2 элемента на месте в атрибуте "".
Вот псевдокод о том, как вы можете попробовать.
function mySort(originals, attributes) {
// Start of your sorting code here
swap(originals, i, j);
swap(attributes, i, j);
// Rest of your sorting code here
}
Ответ 4
У меня была такая же проблема, и я придумал это невероятно простое решение. Сначала объедините связанные элементы в строки в отдельном массиве, затем используйте 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>
Ответ 5
вдохновлен @jwatts1980 answer, и @Alexander ответьте здесь Я объединил оба ответа в быстрый и грязное решение;
Основной массив - это тот, который нужно отсортировать, остальные просто следуют его индексам
ПРИМЕЧАНИЕ: не очень эффективно для очень больших массивов
/* @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"]
]
}
*/
Вероятно, вы захотите изменить структуру подписи/возврата метода, но это должно быть легко. Я сделал это так, потому что мне это нужно
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;
};
Ответ 6
Я искал что-то более общее и функциональное, чем текущие ответы.
Вот что я придумал: реализация es6 (без мутаций!), Которая позволяет вам сортировать столько массивов, сколько вы хотите, используя массив "source"
/**
* 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
Если производительность имеет значение, для этого есть пакет 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)
Ответ 8
Вы можете добавить исходный индекс каждого элемента к значению, отсортировать массив, затем удалить индекс и использовать его для переопределения другого массива. Он будет работать только там, где содержимое является строкой или может быть успешно преобразовано в строки и из них.
Другое решение - сохранить копию исходного массива, затем после сортировки найдите, где находится каждый элемент, и соответствующим образом настройте другой массив.
Ответ 9
Простейшее объяснение - лучшее, слияние массивов, а затем извлечение после сортировки:
создать массив
name_age=["[email protected]","[email protected]","[email protected]"];
сортируйте массив по-прежнему, затем извлеките имя и возраст, вы можете использовать @для конкретизации, где
имя заканчивается и начинается возраст. Возможно, это не метод для пуриста, но у меня такая же проблема и этот мой подход.
Ответ 10
Это решение (моя работа) сортирует несколько массивов без преобразования данных в промежуточную структуру и эффективно работает с большими массивами. Он позволяет передавать массивы в виде списка или объекта и поддерживает пользовательскую функцию сравнения.
Использование:
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)
- Сортируйте индексы с помощью пользовательской функции сравнения, которая сравнивает значения, найденные по индексу
- Для каждого входного массива сопоставьте каждый индекс по порядку с его значением
Реализация:
/**
* 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
Ответ 11
Как насчет:
var names = ["Bob","Tom","Larry"];
var ages = ["10", "20", "30"];
var n = names.slice(0).sort()
var a = [];
for (x in n)
{
i = names.indexOf(n[x]);
a.push(ages[i]);
names[i] = null;
}
names = n
ages = a