Tengo un array de objetos de la siguiente forma:

arr[0] = { 'item1' : 1234, 'item2' : 'a string' };

Clasifico primero 'item1' que es sencillo. Ahora quiero ordenar arr (que está ordenada por 'item1') de nuevo pero esta vez por 'item2' pero sólo para los elementos en los que 'item1' es el mismo. El conjunto final, se vería así:

arr = [
  { 'item1' : 1234, 'item2' : 'apple' },
  { 'item1' : 1234, 'item2' : 'banana' },
  { 'item1' : 1234, 'item2' : 'custard' },
  { 'item1' : 2156, 'item2' : 'melon' },
  { 'item1' : 4345, 'item2' : 'asparagus' } 
];

Traté de escribir una función de clasificación para el segundo caso así:

arr.sort(function(a,b){
  if(a.item1 === b.item1){
    return a.item2 > b.item2 ? 1 : a.item2 < b.item2 : -1 : 0;
  }
});

Podría combinar los dos tipos en una función para obtener el final de la matriz ordenada, pero habrá casos en los que voy a tener que ordenar por sólo 'item1' o simplemente 'item2'.

  • Si se las arregló para ordenar por item1, item2, y dos de ellos, entonces ¿qué estás preguntando exactamente?
  • Así es como escribir un patrón decorador donde yo digo «nueva sortByItem2( nueva sortByItem1(arr))». También quiero usarlo como sortByItem1(arr) o sortByItem2(arr) o «nuevo sortByItem1( nueva sortByItem2(arr))»
InformationsquelleAutor fenderplayer | 2011-08-23

4 Comentarios

  1. 30

    Usted puede tener cuatro diferentes funciones de comparación – una clasificación por elemento1, uno por item2, uno por elemento1, a continuación, item2 y uno por item2, a continuación, elemento1.

    E. g.:

    arr.sort(function(a,b){
      if(a.item1 == b.item1){
        return a.item2 > b.item2 ? 1 : a.item2 < b.item2 ? -1 : 0;
      }
    
      return a.item1 > b.item1 ? 1 : -1;
    });
    • eso es genial cómo simplemente se puede hacer uso de los comparadores de ordenación de las funciones en javascript.
  2. 2

    Llegué a la misma pregunta últimamente. Vino con una solución similar que langpavel, pero yo prefiero a dividir el tema en dos. Primero un encadenado comparador de ayuda que le permite a múltiples especie de regla, cada una aplicada en orden como un desempate en caso de igualdad:

        type Comparator<T> = (a: T, b: T) => number; //-1 | 0 | 1
    
        /**
         * Allow to chain multiple comparators, each one called to break equality from the previous one.
         */
        function chainedComparator<T>(...comparators: Comparator<T>[]): Comparator<T> {
            return (a: T, b: T) => {
                let order = 0;
                let i = 0;
    
                while (!order && comparators[i]) {
                    order = comparators[i++](a, b);
                }
    
                return order;
            };
        }

    Me gusta, porque toma y retorno de ordenación del comparador. Así que si usted tiene una colección de otros comparadores, son fáciles de usar.

    A continuación, usted puede simplificar un poco su vida con un auxiliar adicional. Este retorno a una especie de comparación basado en el resultado del pasado lambda sobre cada uno de los elementos.

        type Comparable = string | number;
    
        /**
         * Returns a comparator which use an evaluationFunc on each item for comparison
         */
        function lambdaComparator<T>(evaluationFunc: ((item: T) => Comparable), reversed = false): Comparator<T> {
            return (a: T, b: T) => {
                const valA = evaluationFunc(a);
                const valB = evaluationFunc(b);
                let order = 0;
    
                if (scoreA < scoreB) {
                    order = -1;
                } else if (scoreA > scoreB) {
                    order = 1;
                }
                return reversed ? -order : order;
            };
        }

    reversed aquí no está obligado a responder a la pregunta, pero permitirá a invertir el orden fácilmente.

    Para responder a la pregunta en concreto, el uso de nuestros dos comparadores:

        arr.sort(chainedComparator(
            lambdaComparator(a => a.item1),
            lambdaComparator(a => a.item2.toLowerCase()) //"banana" before "Melon"
        ));

    Debido a que la pregunta original era en JavaScript puro, de precisión: Si no estás acostumbrado a Máquina, usted puede conseguir JavaScript normal sólo por la eliminación de la tipificación de <T>, : T, : ((item: T) => Comparable) en todas partes y los dos type líneas de salida.

  3. 1

    Estoy usando este helper en el Manuscrito:

    //Source
    type ComparatorSelector<T> = (value: T, other: T) => number | string | null;
    
    export function createComparator<T>(...selectors: ComparatorSelector<T>[]) {
      return (a: T, b: T) => {
        for (const selector of selectors) {
          const valA = selector(a, b);
          if (valA === null) continue;
          const valB = selector(b, a);
          if (valB === null || valA == valB) continue;
          if (valA > valB) return 1;
          if (valA < valB) return -1;
        }
        return 0;
      };
    }

    //Usage:
    const candidates: any[] = [];
    //...
    candidates.sort(createComparator(
      (x) => x.ambiguous,
      (_, y) => y.refCount, //DESC
      (x) => x.name.length,
      (x) => x.name,
    ));
  4. 0

    O como simple oneliner para la primera y segunda prioridad de ordenación, puede ampliarlo como usted desea, sólo tiene que sustituir el 0 con otra comparación de la cadena. Interruptor de < y > o -1 y 1 para el orden inverso.

    someArray.sort(function(a,b) {
      return a.item1 > b.item1 ? 1 : a.item1 < b.item1 ? -1 : a.item2 > b.item2 ? 1 : a.item2 < b.item2 ? -1 : 0;
    });

Dejar respuesta

Please enter your comment!
Please enter your name here