Ordenar una matriz de JavaScript basada en otra matriz

Resuelto user1448892 asked hace 12 años • 29 respuestas

¿Es posible ordenar y reorganizar una matriz similar a la siguiente?

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

para que coincida con la disposición de esta matriz:

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

Desafortunadamente, no tengo ninguna identificación para realizar un seguimiento. Necesitaría priorizar la matriz de elementos para que coincida con sortingArr lo más cerca posible.

Aquí está el resultado que estoy buscando:

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

¿Cómo se puede hacer esto?

user1448892 avatar Nov 09 '12 15:11 user1448892
Aceptado

Respuesta de una línea.

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

O incluso más corto:

itemsArray.sort((a, b) => sortingArr.indexOf(a) - sortingArr.indexOf(b));
Durgpal Singh avatar May 19 '2017 06:05 Durgpal Singh

Algo como:

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

Aquí hay un código más corto, pero destruye la sortingmatriz:

result = items.map(function(item) {
    var n = sorting.indexOf(item[1]);
    sorting[n] = '';
    return [n, item]
}).sort().map(function(j) { return j[1] })
georg avatar Nov 09 '2012 08:11 georg

Si usa la función de clasificación de matriz nativa, puede pasar un comparador personalizado para usarlo al ordenar la matriz. El comparador debe devolver un número negativo si el primer valor es menor que el segundo, cero si son iguales y un número positivo si el primer valor es mayor.

Entonces, si entiendo correctamente el ejemplo que estás dando, podrías hacer algo como:

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

itemsArray.sort(sortFunc);
David Lewis avatar Nov 09 '2012 08:11 David Lewis

Caso 1: Pregunta original (sin bibliotecas)

Muchas otras respuestas que funcionan. :)

Caso 2: Pregunta original (Lodash.js o Underscore.js)

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

Caso 3: Ordenar Array1 como si fuera Array2

Supongo que la mayoría de la gente vino aquí buscando un equivalente a array_multisort de PHP (yo lo hice), así que pensé en publicar esa respuesta también. Hay un par de opciones:

1. Existe una implementación JS de array_multisort() . Gracias a @Adnan por señalarlo en los comentarios. Aunque es bastante grande.

2. Escribe el tuyo propio. ( Demostración de 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.js o Underscore.js (ambas bibliotecas populares y más pequeñas que se centran en el rendimiento) ofrecen funciones auxiliares que le permiten hacer esto:

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

... Lo que (1) agrupará sortArray en [index, value]pares, (2) los ordenará por valor (también puede proporcionar una devolución de llamada aquí), (3) reemplazará cada uno de los pares con el elemento de itemArray en el índice del par se originó de.

Don McCurdy avatar Dec 05 '2014 05:12 Don McCurdy