Comment trier un tableau multi dimensionnel par plusieurs colonnes en JavaScript?
J'ai travaillé sur ce problème toute la journée sans une bonne solution. Google a été de peu d'aide. J'ai un script qui doit accepter un tableau à deux dimensions avec un nombre inconnu nombre de lignes/colonnes. Le script doit également accepter un dimensions tableau contenant une liste de colonnes à trier, et l'autre contenant l'ordre de tri. L'appel ressemble un peu à ceci:
var orderList = {0,4,3,1};
var orderDir = {asc,desc,desc,asc};
dataArr = do2DArraySort(dataArr, orderList, orderDir);
La fonction do2DArraySort doit retourner le dataArr tableau trié par la première colonne (en ordre croissant), puis par le cinquième (en ordre décroissant), puis par le troisième (en ordre décroissant), puis par le deuxième (en ordre décroissant). J'ai été capable de le faire à deux niveaux de profondeur à l'aide du code ci-dessous, mais il est tombé à part une fois que j'ai essayé d'ajouter une troisième colonne de tri. Je comprends pourquoi, mais je ne peux pas trouver un bon moyen de le faire fonctionner.
Est-il un moyen standard de le faire? Quelqu'un pourrait-il m'indiquer un bon script en ligne je peux étude et l'utiliser comme un modèle? Ou quelqu'un peut-il suggérer une modification à mon code pour le faire fonctionner?
Merci!
//appends an array content to the original array
function addToArray(originalArray, addArray) {
if (addArray.length != 0) {
var curLength = 0;
curLength = originalArray.length;
var maxLength = 0;
maxLength = curLength + addArray.length;
var itrerateArray = 0;
for (var r = curLength; r < maxLength; r++) {
originalArray[r] = addArray[itrerateArray];
itrerateArray++;
}
}
}
function do2DArraySort(arrayToBeSorted, sortColumnArray, sortDirectionArray) {
if (arrayToBeSorted == "undefined" || arrayToBeSorted == "null") return arrayToBeSorted;
if (arrayToBeSorted.length == 0) return arrayToBeSorted;
if (sortColumnArray.length == 0) return arrayToBeSorted;
tempArray = arrayToBeSorted;
var totalLength = sortColumnArray.length;
for(var m = 0; m < totalLength; m++) {
if (m == 0) {
doBubbleSort(tempArray, tempArray.length, sortColumnArray[m], sortDirectionArray[m]);
} else {
doMultipleSort(tempArray, sortColumnArray[m], sortColumnArray[m-1], sortDirectionArray[m]);
}
}
return tempArray;
}
//check if a value exists in a single dimensional array
function checkIfExists(arrayToSearch, valueToSearch) {
if (arrayToSearch == "undefined" || arrayToSearch == "null") return false;
if (arrayToSearch.length == 0) return false;
for (var k = 0; k < arrayToSearch.length; k++) {
if (arrayToSearch[k] == valueToSearch) return true;
}
return false;
}
//sorts an 2D array based on the distinct values of the previous column
function doMultipleSort(sortedArray, currentCol, prevCol, sortDirection) {
var resultArray = new Array();
var newdistinctValuesArray = new Array();
//finding distinct previous column values
for (var n = 0; n < sortedArray.length; n++) {
if (checkIfExists(newdistinctValuesArray, sortedArray[n][prevCol]) == false) newdistinctValuesArray.push(sortedArray[n][prevCol]);
}
var recCursor = 0;
var newTempArray = new Array(); var toStoreArray = 0;
//for each of the distinct values
for (var x = 0; x < newdistinctValuesArray.length; x++) {
toStoreArray = 0;
newTempArray = new Array();
//find the rows with the same previous column value
for (var y = 0; y < sortedArray.length; y++) {
if (sortedArray[y][prevCol] == newdistinctValuesArray[x]) {
newTempArray[toStoreArray] = sortedArray[y];
toStoreArray++;
}
} //sort the row based on the current column
doBubbleSort(newTempArray, newTempArray.length, currentCol, sortDirection);
//append it to the result array
addToArray(resultArray, newTempArray);
}
tempArray = resultArray;
}
OriginalL'auteur Nicholas | 2011-05-23
Vous devez vous connecter pour publier un commentaire.
Le littéral de tableau
[]
est préféré aunew Array
. La notation{0,4,3,1}
n'est pas valide et doit être[0,4,3,1]
.Est-il nécessaire de réinventer la roue? Deux tableaux peut être joint à l'aide de:
Éléments peuvent être ajoutés à la fin de l'aide:
Tableaux ont une méthode pour trier le tableau. Par défaut, c'est par ordre numérique:
Les tableaux peuvent être inversés. En poursuivant l'exemple précédent:
De fournir un tri personnalisé, vous pouvez passer l'option argument de fonction à
array.sort()
:Éléments conservent leur position si l'élément est égal à un autre élément. En utilisant cela, vous pouvez combiner plusieurs de tri algoritms. Vous devez appliquer vos préférences de tri dans l'ordre inverse depuis le dernier tri a la priorité sur les précédents. Pour trier le tableau ci-dessous par la première colonne (par ordre décroissant), puis la deuxième colonne (par ordre croissant):
Pour trier latine cordes (c'est à dire l'anglais, l'allemand, le néerlandais), l'utilisation
String.localeCompare
:Pour trier date de la
Date
objet, utiliser leurs millisecondes représentation:Vous pouvez appliquer cette fonction de tri à tous les types de données, il suffit de suivre les règles:
x
est le résultat de la comparaison entre deux valeurs qui doivent être renvoyées par une fonction transmise àarray.sort
.x < 0
:element_a
devrait venir avantelement_b
x = 0
:element_a
etelement_b
sont égaux, les éléments ne sont pas échangésx > 0
:element_a
devrait venir aprèselement_b
J'ai inclus un exemple pour le tri des dates de la
Date
objet et les chaînes de caractères. Si vous comprenez l'utilisation de tableaux et de connaître un peu de Javascript, vous pouvez trier tout à condition que vous ayez les exigences pour l'algorithme de tri. Devrait-il être incertaine, ajouter un commentaire, il peut être expliqué.Lekensteyn; encore merci. Je crois que je comprends assez bien (dangereux) maintenant ;). J'ai trouvé que l'algorithme de tri qui semble bien fonctionner sur les dates sans avoir à utiliser la méthode getTime. Ai-je raté une des pièges dans la sauter? Vous êtes un vrai de la vie de veille. 🙂
si votre "date" est une chaîne, vous devez le convertir en une première date:
(new Date("Thu, 21 Dec 2000 16:01:07 +0200")).getTime()
. Pour les tableaux de grande taille, il peut être préférable de mettre en cache le résultat, et l'utilisation qui en cache le résultat de la comparaison.C'est plutôt une bonne réponse, mais il ya un hic: Lekensteyn états sur le Tableau.le prototype.méthode sort() que des "Éléments conservent leur position si l'élément est égal à un autre élément", mais l'ECMAScript spec dit explicitement que les implémentations n'ont PAS à le faire, et certains navigateurs ne le font pas. Google Chrome ne fonctionne pas, et l'Opéra ne l'est pas. Par conséquent, vous ne pouvez PAS attendre plusieurs appels ultérieurs à trier() se comporte de la façon dont vous vous attendez dans les navigateurs.
OriginalL'auteur Lekensteyn
Je suggère d'écrire une fonction d'ordre supérieur qui prend la orderList et orderDir comme arguments et retourne un comparateur de fonction qui peuvent être transmis directement à la Matrice#tri. De cette façon, vous pouvez essayer différentes implémentations (dont le commerce hors simplicité pour les performances, par exemple).
Ce code non testé illustre l'idée:
Notez que vous aurez envie d'être prudent sur l'utilisation de "localeCompare" vs soustraction pour les chaînes vs nombres, de sorte que peut-être cet aspect peut être paramétrée à l'getComparator de la fonction en tant que bien.
OriginalL'auteur maerics
Basé sur Lekensteyn est une excellente réponse, j'ai développé la solution suivante pour mes besoins. Je n'ai pas fait le plein les contrôles de qualité sur encore et de la ne sais pas si c'est parfait (en fait, je suis assez sûr qu'il ne l'est pas), mais j'espère que d'autres personnes peuvent obtenir de l'utilisation de ce et de s'en inspirer pour leurs besoins. Je vais poster une mise à jour si des changements majeurs nécessaires faite.
OriginalL'auteur Nicholas