基于另一个数组对数组进行排序

是否有可能对一个数组进行排序和重排,看起来像这样:

itemsArray = [
['Anne', 'a'],
['Bob', 'b'],
['Henry', 'b'],
['Andrew', 'd'],
['Jason', 'c'],
['Thomas', 'b']
]

要匹配此数组的排列:

sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ]

不幸的是,我没有任何身份证件可以追踪。我需要优先考虑items-array以尽可能接近地匹配sortingArr。

更新:

以下是我正在寻找的输出:

itemsArray = [
['Bob', 'b'],
['Jason', 'c'],
['Henry', 'b'],
['Thomas', 'b']
['Anne', 'a'],
['Andrew', 'd'],
]

知道该怎么做吗?

243430 次浏览

使用jQuery的$. inarray()方法。然后你可以这样做

var sortingArr = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
var newSortedArray = new Array();


for(var i=sortingArr.length; i--;) {
var foundIn = $.inArray(sortingArr[i], itemsArray);
newSortedArray.push(itemsArray[foundIn]);
}

你可以这样做:

function getSorted(itemsArray , sortingArr ) {
var result = [];
for(var i=0; i<arr.length; i++) {
result[i] = arr[sortArr[i]];
}
return result;
}

你可以在这里进行测试

注意:假设你传入的数组在大小上是相等的,如果情况并非如此,你需要添加一些额外的检查。

参考链接

5427223 < a href = " https://stackoverflow.com/questions/5427141/quickest-way-to-sort-a-js-array-based-on-another-arrays-values/5427223 " > < / >引用

如果使用本机数组排序函数,则可以传入一个自定义比较器,以便在对数组排序时使用。如果第一个值小于第二个值,比较器应该返回一个负数;如果它们相等,则返回零;如果第一个值大于第二个值,则返回正数。

所以如果我正确理解了你给出的例子,你可以这样做:

function sortFunc(a, b) {
var sortingArr = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
return sortingArr.indexOf(a[1]) - sortingArr.indexOf(b[1]);
}


itemsArray.sort(sortFunc);

喜欢的东西:

items = [
['Anne', 'a'],
['Bob', 'b'],
['Henry', 'b'],
['Andrew', 'd'],
['Jason', 'c'],
['Thomas', 'b']
]


sorting = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
result = []


sorting.forEach(function(key) {
var found = false;
items = items.filter(function(item) {
if(!found && item[1] == key) {
result.push(item);
found = true;
return false;
} else
return true;
})
})


result.forEach(function(item) {
document.writeln(item[0]) /// Bob Jason Henry Thomas Andrew
})

下面是一个较短的代码,但它破坏了sorting数组:

result = items.map(function(item) {
var n = sorting.indexOf(item[1]);
sorting[n] = '';
return [n, item]
}).sort().map(function(j) { return j[1] })

这应该是有效的:

var i,search, itemsArraySorted = [];
while(sortingArr.length) {
search = sortingArr.shift();
for(i = 0; i<itemsArray.length; i++) {
if(itemsArray[i][1] == search) {
itemsArraySorted.push(itemsArray[i]);
break;
}
}
}


itemsArray = itemsArraySorted;
var sortedArray = [];
for(var i=0; i < sortingArr.length; i++) {
var found = false;
for(var j=0; j < itemsArray.length && !found; j++) {
if(itemsArray[j][1] == sortingArr[i]) {
sortedArray.push(itemsArray[j]);
itemsArray.splice(j,1);
found = true;
}
}
}

http://jsfiddle.net/s7b2P/

结果顺序:鲍勃,杰森,亨利,托马斯,安妮,安德鲁

我将使用一个中间对象(itemsMap),从而避免二次复杂度:

function createItemsMap(itemsArray) { // {"a": ["Anne"], "b": ["Bob", "Henry"], …}
var itemsMap = {};
for (var i = 0, item; (item = itemsArray[i]); ++i) {
(itemsMap[item[1]] || (itemsMap[item[1]] = [])).push(item[0]);
}
return itemsMap;
}


function sortByKeys(itemsArray, sortingArr) {
var itemsMap = createItemsMap(itemsArray), result = [];
for (var i = 0; i < sortingArr.length; ++i) {
var key = sortingArr[i];
result.push([itemsMap[key].shift(), key]);
}
return result;
}

看到http://jsfiddle.net/eUskE/

案例1:原始问题(没有图书馆)

还有很多其他有用的答案。:)

案例2:原始问题(Lodash.js或Underscore.js)

var groups = _.groupBy(itemArray, 1);
var result = _.map(sortArray, function (i) { return groups[i].shift(); });

情形3:把Array1当作Array2来排序

我猜大多数人来这里是为了寻找PHP的array_multisort(我做过),所以我想我也会把这个答案贴出来。这里有几个选项:

1. 有一个现有的JS实现array_multisort()。感谢@Adnan在评论中指出这一点。不过,它相当大。

2. 自己写。(JSFiddle演示)

function refSort (targetData, refData) {
// Create an array of indices [0, 1, 2, ...N].
var indices = Object.keys(refData);


// Sort array of indices according to the reference data.
indices.sort(function(indexA, indexB) {
if (refData[indexA] < refData[indexB]) {
return -1;
} else if (refData[indexA] > refData[indexB]) {
return 1;
}
return 0;
});


// Map array of indices to corresponding values of the target array.
return indices.map(function(index) {
return targetData[index];
});
}

3.Lodash.jsUnderscore.js(两者都是流行的,较小的库,专注于性能)提供帮助函数,允许你这样做:

    var result = _.chain(sortArray)
.pairs()
.sortBy(1)
.map(function (i) { return itemArray[i[0]]; })
.value();

...它将(1)将sortArray分组为[index, value]对,(2)根据值对它们排序(你也可以在这里提供一个回调),(3)将每个对替换为itemArray中位于该对产生的索引处的项。

使用两个数组的交集。

例:

var sortArray = ['a', 'b', 'c',  'd', 'e'];


var arrayToBeSort = ['z', 's', 'b',  'e', 'a'];


_.intersection(sortArray, arrayToBeSort)

=> ['a', 'b', 'e']

如果'z '和's'不在第一个数组的范围内,则将其附加在result的末尾

这可能太迟了,但是,你也可以使用下面ES6风格的修改版本的代码。这段代码用于如下数组:

var arrayToBeSorted = [1,2,3,4,5];
var arrayWithReferenceOrder = [3,5,8,9];

实际操作:

arrayToBeSorted = arrayWithReferenceOrder.filter(v => arrayToBeSorted.includes(v));

ES5的实际操作:

arrayToBeSorted = arrayWithReferenceOrder.filter(function(v) {
return arrayToBeSorted.includes(v);
});

应该导致arrayToBeSorted = [3,5]

不销毁引用数组。

我必须为从API接收到的JSON有效负载这样做,但它不是我想要的顺序。

数组作为参考数组,你想要排序的第二个数组:

var columns = [
{last_name: "last_name"},
{first_name: "first_name"},
{book_description: "book_description"},
{book_id: "book_id"},
{book_number: "book_number"},
{due_date: "due_date"},
{loaned_out: "loaned_out"}
];

我把它们作为对象是因为它们最终会有其他属性。

创建数组:

 var referenceArray= [];
for (var key in columns) {
for (var j in columns[key]){
referenceArray.push(j);
}
}

与数据库中的结果集一起使用。我不知道它的效率如何,但由于我使用的列的数量很少,它工作得很好。

result.forEach((element, index, array) => {
var tr = document.createElement('tr');
for (var i = 0; i < referenceArray.length - 1; i++) {
var td = document.createElement('td');
td.innerHTML = element[referenceArray[i]];
tr.appendChild(td);


}
tableBody.appendChild(tr);
});

一行的答案。

itemsArray.sort(function(a, b){
return sortingArr.indexOf(a) - sortingArr.indexOf(b);
});

或者更短:

itemsArray.sort((a, b) => sortingArr.indexOf(a) - sortingArr.indexOf(b));
let a = ['A', 'B', 'C' ]


let b = [3, 2, 1]


let c = [1.0, 5.0, 2.0]


// these array can be sorted by sorting order of b


const zip = rows => rows[0].map((_, c) => rows.map(row => row[c]))


const sortBy = (a, b, c) => {
const zippedArray = zip([a, b, c])
const sortedZipped = zippedArray.sort((x, y) => x[1] - y[1])


return zip(sortedZipped)
}


sortBy(a, b, c)

这是我正在寻找的,我根据另一个数组对数组的数组进行排序:

它是On^3,可能不是最佳实践(ES6)

function sortArray(arr, arr1){
return arr.map(item => {
let a = [];
for(let i=0; i< arr1.length; i++){
for (const el of item) {
if(el == arr1[i]){
a.push(el);
}
}
}
return a;
});
}
    

const arr1 = ['fname', 'city', 'name'];
const arr = [['fname', 'city', 'name'],
['fname', 'city', 'name', 'name', 'city','fname']];
console.log(sortArray(arr,arr1));
它可能会帮助别人

为了获得一个新的有序数组,你可以取Map并收集数组中具有所需键的所有项,并通过取所需组的筛选元素来映射所需的有序键。

var itemsArray = [['Anne', 'a'], ['Bob', 'b'], ['Henry', 'b'], ['Andrew', 'd'], ['Jason', 'c'], ['Thomas', 'b']],
sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ],
map = itemsArray.reduce((m, a) => m.set(a[1], (m.get(a[1]) || []).concat([a])), new Map),
result = sortingArr.map(k => (map.get(k) || []).shift());


console.log(result);

你可以试试这个方法。

const sortListByRanking = (rankingList, listToSort) => {
let result = []


for (let id of rankingList) {
for (let item of listToSort) {
if (item && item[1] === id) {
result.push(item)
}
}
}


return result
}

为什么不像

//array1: array of elements to be sorted
//array2: array with the indexes


array1 = array2.map((object, i) => array1[object]);

Javascript的所有版本上可能都无法使用map函数

let sortedOrder = [ 'b', 'c', 'b', 'b' ]
let itemsArray = [
['Anne', 'a'],
['Bob', 'b'],
['Henry', 'b'],
['Andrew', 'd'],
['Jason', 'c'],
['Thomas', 'b']
]
a.itemsArray(function (a, b) {
let A = a[1]
let B = b[1]


if(A != undefined)
A = A.toLowerCase()


if(B != undefined)
B = B.toLowerCase()


let indA = sortedOrder.indexOf(A)
let indB = sortedOrder.indexOf(B)


if (indA == -1 )
indA = sortedOrder.length-1
if( indB == -1)
indB = sortedOrder.length-1


if (indA < indB ) {
return -1;
} else if (indA > indB) {
return 1;
}
return 0;
})

如果排序键在引用数组中不存在,此解决方案将在末尾附加对象

ES6

const arrayMap = itemsArray.reduce(
(accumulator, currentValue) => ({
...accumulator,
[currentValue[1]]: currentValue,
}),
{}
);
const result = sortingArr.map(key => arrayMap[key]);

更多的例子使用不同的输入数组

如果你在这里需要用一个对象数组来做这件事,这里是@Durgpal Singh的精彩答案的改编:

const itemsArray = [
{ name: 'Anne', id: 'a' },
{ name: 'Bob', id: 'b' },
{ name: 'Henry', id: 'b' },
{ name: 'Andrew', id: 'd' },
{ name: 'Jason', id: 'c' },
{ name: 'Thomas', id: 'b' }
]


const sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ]


Object.keys(itemsArray).sort((a, b) => {
return sortingArr.indexOf(itemsArray[a].id) - sortingArr.indexOf(itemsArray[b].id);
})

function sortFunc(a, b) {
var sortingArr = ["A", "B", "C"];
return sortingArr.indexOf(a.type) - sortingArr.indexOf(b.type);
}


const itemsArray = [
{
type: "A",
},
{
type: "C",
},
{
type: "B",
},
];
console.log(itemsArray);
itemsArray.sort(sortFunc);
console.log(itemsArray);

用数值排序:

itemsArray.sort(function(a, b){
return sortingArr[itemsArray.indexOf(a)] - sortingArr[itemsArray.indexOf(b)];
});
this.arrToBeSorted =  this.arrToBeSorted.sort(function(a, b){
return uppthis.sorrtingByArray.findIndex(x => x.Id == a.ByPramaeterSorted) - uppthis.sorrtingByArray.findIndex(x => x.Id == b.ByPramaeterSorted);
});
  const result = sortingArr.map((i) => {
const pos = itemsArray.findIndex(j => j[1] === i);
const item = itemsArray[pos];
itemsArray.splice(pos, 1);
return item;
});

这似乎对我很管用:

var outputArray=['10','6','8','10','4','6','2','10','4','0','2','10','0'];
var template=['0','2','4','6','8','10'];
var temp=[];


for(i=0;i<template.length;i++) {
for(x=0;x<outputArray.length;x++){
if(template[i] == outputArray[x]) temp.push(outputArray[x])
};
}


outputArray = temp;
alert(outputArray)

我希望我能帮助到一些人,但是如果你试图通过第一个数组的键上的另一个数组对一个对象数组进行排序,例如,你想对这个对象数组进行排序:

const foo = [
{name: 'currency-question', key: 'value'},
{name: 'phone-question', key: 'value'},
{name: 'date-question', key: 'value'},
{name: 'text-question', key: 'value'}
];

通过这个数组:

const bar = ['text-question', 'phone-question', 'currency-question', 'date-question'];

你可以这样做:

foo.sort((a, b) => bar.indexOf(a.name) - bar.indexOf(b.name));