Javascript:Seřadit pole a vrátit pole indexů, které označují pozici seřazených prvků vzhledem k původním prvkům

Předpokládejme, že mám pole Javascript, například:

var test = ['b', 'c', 'd', 'a'];

Chci třídit pole. Je zřejmé, že to mohu udělat jen pro seřazení pole:

test.sort(); //Now test is ['a', 'b', 'c', 'd']

Ale to, co opravdu chci, je pole indexů, které udávají polohu seřazených prvků vzhledem k původním prvkům. Nejsem si úplně jistý, jak to formulovat, takže možná proto mám problém přijít na to, jak to udělat.

Pokud by se taková metoda jmenovala sortIndices(), pak bych chtěl:

var indices = test.sortIndices();
//At this point, I want indices to be [3, 0, 1, 2].

„a“ bylo na pozici 3, „b“ bylo na 0, „c“ bylo na 1 a „d“ bylo 2 v původním poli. Proto [3, 0, 1, 2].

Jedním z řešení by bylo seřadit kopii pole a poté procházet setříděné pole a najít pozici každého prvku v původním poli. Ale, to mi přijde neohrabané.

Existuje nějaká existující metoda, která dělá to, co chci? Pokud ne, jak byste postupovali při psaní metody, která to dělá?

Odpověď

var test = ['b', 'c', 'd', 'a'];
var test_with_index = [];
for (var i in test) {
    test_with_index.push([test[i], i]);
}
test_with_index.sort(function(left, right) {
  return left[0] < right[0] ? -1 : 1;
});
var indexes = [];
test = [];
for (var j in test_with_index) {
    test.push(test_with_index[j][0]);
    indexes.push(test_with_index[j][1]);
}

Upravit

Máte pravdu ohledně for .. in . To se zlomí, pokud někdo zničí prototyp pole, což pozoruji nepříjemně často. Tady je to s tím opraveným a zabaleným do použitelnější funkce.

function sortWithIndeces(toSort) {
  for (var i = 0; i < toSort.length; i++) {
    toSort[i] = [toSort[i], i];
  }
  toSort.sort(function(left, right) {
    return left[0] < right[0] ? -1 : 1;
  });
  toSort.sortIndices = [];
  for (var j = 0; j < toSort.length; j++) {
    toSort.sortIndices.push(toSort[j][1]);
    toSort[j] = toSort[j][0];
  }
  return toSort;
}

var test = ['b', 'c', 'd', 'a'];
sortWithIndeces(test);
alert(test.sortIndices.join(","));