145 votes

Comment trier un tableau sur plusieurs colonnes ?

J'ai un tableau multidimensionnel. Le tableau primaire est un tableau de

[publicationID][publication_name][ownderID][owner_name] 

Ce que j'essaie de faire, c'est de trier le tableau par owner_name et ensuite par publication_name . Je sais qu'en JavaScript vous avez Array.sort() dans lequel vous pouvez placer une fonction personnalisée, dans mon cas j'ai :

function mysortfunction(a, b) {
    var x = a[3].toLowerCase();
    var y = b[3].toLowerCase();

    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}

Cela convient pour trier sur une seule colonne, à savoir owner_name, mais comment puis-je le modifier pour trier sur owner_name entonces publication_name ?

15voto

Nina Scholz Points 17120

Je suggère d'utiliser un comparateur intégré et d'enchaîner l'ordre de tri désiré avec un ordre logique ou un ordre de priorité. || .

function customSort(a, b) {
    return a[3].localeCompare(b[3]) || a[1].localeCompare(b[1]);
}

Exemple de travail :

var array = [
    [0, 'Aluminium', 0, 'Francis'],
    [1, 'Argon', 1, 'Ada'],
    [2, 'Brom', 2, 'John'],
    [3, 'Cadmium', 3, 'Marie'],
    [4, 'Fluor', 3, 'Marie'],
    [5, 'Gold', 1, 'Ada'],
    [6, 'Kupfer', 4, 'Ines'],
    [7, 'Krypton', 4, 'Joe'],
    [8, 'Sauerstoff', 3, 'Marie'],
    [9, 'Zink', 5, 'Max']
];

array.sort(function (a, b) {
    return a[3].localeCompare(b[3]) || a[1].localeCompare(b[1]);
});

document.write('<pre>');
array.forEach(function (a) {
    document.write(JSON.stringify(a) + '<br>');
});

8voto

Tmac Points 599

Vous pourriez concaténer les deux variables en une clé de tri et l'utiliser pour votre comparaison.

list.sort(function(a,b){
   var aCat = a.var1 + a.var2;
   var bCat = b.var1 + b.var2;
   return (aCat > bCat ? 1 : aCat < bCat ? -1 : 0);
});

6voto

MiF Points 326

J'ai trouvé multisotr . Il s'agit d'une petite bibliothèque simple et puissante pour les tris multiples. J'avais besoin de trier un tableau d'objets avec des critères de tri dynamiques :

const criteria = ['name', 'speciality']
const data = [
  { name: 'Mike', speciality: 'JS', age: 22 },
  { name: 'Tom', speciality: 'Java', age: 30 },
  { name: 'Mike', speciality: 'PHP', age: 40 },
  { name: 'Abby', speciality: 'Design', age: 20 },
]

const sorted = multisort(data, criteria)

console.log(sorted)

<script src="https://cdn.rawgit.com/peterkhayes/multisort/master/multisort.js"></script>

Cette bibliothèque est plus puissante, c'était mon cas. Essayez-la.

4voto

Michael Warner Points 1179

Méthode d'ajout de chaîne

Vous pouvez trier par valeurs multiples en ajoutant simplement les valeurs dans une chaîne et en comparant les chaînes. Il est utile d'ajouter un caractère de séparation des touches pour empêcher le passage d'une touche à l'autre.

Ejemplo

const arr = [ 
    { a: 1, b: 'a', c: 3 },
    { a: 2, b: 'a', c: 5 },
    { a: 1, b: 'b', c: 4 },
    { a: 2, b: 'a', c: 4 }
]

function sortBy (arr, keys, splitKeyChar='~') {
    return arr.sort((i1,i2) => {
        const sortStr1 = keys.reduce((str, key) => str + splitKeyChar+i1[key], '')
        const sortStr2 = keys.reduce((str, key) => str + splitKeyChar+i2[key], '')
        return sortStr1.localeCompare(sortStr2)
    })
}

console.log(sortBy(arr, ['a', 'b', 'c']))

Méthode de récursivité

Vous pouvez également utiliser la récursivité pour ce faire. C'est un peu plus complexe que la méthode d'addition de chaînes de caractères, mais cela vous permet de faire des ASC et des DESC au niveau des clés. Je commente chaque section car elle est un peu plus complexe.

Il y a quelques tests commentés pour montrer et vérifier que le tri fonctionne avec un mélange d'ordre et d'ordre par défaut.

Ejemplo

const arr = [ 
    { a: 1, b: 'a', c: 3 },
    { a: 2, b: 'a', c: 5 },
    { a: 1, b: 'b', c: 4 },
    { a: 2, b: 'a', c: 4 }
]

function sortBy (arr, keys) {
    return arr.sort(function sort (i1,i2, sKeys=keys) {
        // Get order and key based on structure
        const compareKey = (sKeys[0].key) ? sKeys[0].key : sKeys[0];
        const order = sKeys[0].order || 'ASC'; // ASC || DESC
        // Calculate compare value and modify based on order
        let compareValue = i1[compareKey].toString().localeCompare(i2[compareKey].toString())
        compareValue = (order.toUpperCase() === 'DESC') ? compareValue * -1 : compareValue
        // See if the next key needs to be considered 
        const checkNextKey = compareValue === 0 && sKeys.length !== 1
        // Return compare value
        return (checkNextKey) ? sort(i1, i2, sKeys.slice(1)): compareValue;
    })
}

// console.log(sortBy(arr, ['a', 'b', 'c']))
console.log(sortBy(arr, [{key:'a',order:'desc'}, 'b', 'c']))
// console.log(sortBy(arr, ['a', 'b', {key:'c',order:'desc'}]))
// console.log(sortBy(arr, ['a', {key:'b',order:'desc'}, 'c']))
// console.log(sortBy(arr, [{key:'a',order:'asc'}, {key:'b',order:'desc'}, {key:'c',order:'desc'}]))

3voto

Kamil Kiełczewski Points 6496

Essayez ceci :

t.sort( (a,b)=> a[3].localeCompare(b[3]) || a[1].localeCompare(b[1]) );

let t = [
    //[publicationID, publication_name, ownderID, owner_name ]
    [1, 'ZBC', 3, 'John Smith'],
    [2, 'FBC', 5, 'Mike Tyson'],
    [3, 'ABC', 7, 'Donald Duck'],
    [4, 'DBC', 1, 'Michael Jackson'],
    [5, 'XYZ', 2, 'Michael Jackson'],
    [6, 'BBC', 4, 'Michael Jackson'],
  ]; 

  // owner_name subarrray index = 3
  // publication_name subarrray index = 1

t.sort( (a,b)=> a[3].localeCompare(b[3]) || a[1].localeCompare(b[1]) );

console.log(t.join('\n'));

Je suppose que vos données se trouvent dans un tableau let t = [ [publicationID, publication_name, ownderID, owner_name ], ... ] où l'index du nom du propriétaire = 3 et du nom de la publication =1.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X