Tri d'un array multidimensionnel par colonne

Signaler
Messages postés
440
Date d'inscription
mardi 21 octobre 2003
Statut
Membre
Dernière intervention
6 mai 2010
-
Messages postés
177
Date d'inscription
jeudi 5 octobre 2006
Statut
Membre
Dernière intervention
16 janvier 2009
-
Salut à tous,

Comment peut t'on procéder pour
trier un tableau multidimensionnel (le mien n'a que 2 colonnes) par la
deuxième colonne par exemple. car en fait j'ai une fonction qui insère
récursivement, au chargement de la page, des données ex:
add_array("http://www.dpm-motors.com/","ASTON MARTIN","Vanquish S","","Noir","12 000","Cuir noir","2005","08/09/2005","","220 000 EUR","Aston5859.JPG|Aston5859A.JPG|Aston5859B.JPG");
add_array("http://www.dpm-motors.com/","AUDI","A3 1,8 L Turbo Quattro","","Bleu","63 036","Cuir beige","2003","06/01/2003","PDC, CD, 5P.Ambiente","14 800 EUR","AUDIA5678.JPG");

function add_array(url_garage,marque,modele,categorie,couleur,kilometrage,interieur,millesime,immat,option,prix_ttc,photo){
var id=fiches_array.length;
fiches_array[id]=new Array();
fiches_array[id][1]=marque;
fiches_array[id][2]=modele;
fiches_array[id][3]=categorie;
fiches_array[id][4]=kilometrage;
fiches_array[id][5]=couleur;
fiches_array[id][6]=interieur;
fiches_array[id][7]=option;
fiches_array[id][8]=prix_ttc;
fiches_array[id][9]=photo;
fiches_array[id][10]=immat;
}
et
en fait je voudrais trier par marque ou bien par modele, j'ai essayé
fiches_array.sort();, ca me trie par rapport à la 1ère colonne, mais je
peux pas trier par rapport aux autres.

Merci d'avance
A voir également:

19 réponses

Messages postés
177
Date d'inscription
jeudi 5 octobre 2006
Statut
Membre
Dernière intervention
16 janvier 2009
1
Bonjour,
implémente toi un petit tri à bulle
et définit une fonction de comparaison qui prend deux objets.
Cordialement,
Pierrick
Messages postés
177
Date d'inscription
jeudi 5 octobre 2006
Statut
Membre
Dernière intervention
16 janvier 2009
1
Je me suis rappelé que le tri a bulle n'est pas trop perfectionné,
donc voici l'implémentation pour ton besoin avec un tri par fusion o(nlogn),
Il te faut rajouter les autres propriétés de comparaison,
Les fonctions de tri sont à peines tester alors si c'est pour de la prod, jettes y un coup d'oeil sérieux.
Cordialement,
Pierrick
<----------------------------------------------------------------------------------------------------------------->

<html>
<head>
<title></title>
<script language="javascript" type="text/javascript">
<!--
var fiches_array = [];

function add_array(url_garage,marque,modele,categorie,couleur,kilometrage,interieur,millesime,immat,option,prix_ttc,photo){
var id=fiches_array.length;
fiches_array[id]=new Array();
fiches_array[id][1]=marque;
fiches_array[id][2]=modele;
fiches_array[id][3]=categorie;
fiches_array[id][4]=kilometrage;
fiches_array[id][5]=couleur;
fiches_array[id][6]=interieur;
fiches_array[id][7]=option;
fiches_array[id][8]=prix_ttc;
fiches_array[id][9]=photo;
fiches_array[id][10]=immat;
}

function compareObjet(o1, o2, sortColumn, sortOrder){
    if( sortColumn == "modele"){
        return sortOrder > 0 ? o1[2] < o2[2] : o1[2] > o2[2];
    }else{
        return sortOrder > 0 ? o1[1] < o2[1] : o1[1] > o2[1];
    }
}

function fusion(t, tmp, de1, vers1, de2, vers2, count, posInB, sortColumn, sortOrder)
{
       for(var i = 0 ; i < count ; i++)
       {
               if(de2 > vers2)
                       tmp[posInB++] = t[de1++];
               else if(de1 > vers1)
                       tmp[posInB++] = t[de2++];
               else if(compareObjet(t[de1], t[de2], sortColumn, sortOrder))
                       tmp[posInB++] = t[de1++];
               else
                       tmp[posInB++] = t[de2++];
       }
       return tmp;
}
 
function triFusion(t, sortColumn, sortOrder)
{
       var tmp = [];
       var sortLength = 1, de1, de2, de3, i;
       while(sortLength < t.length)
       {
               de1 = 0;
               while(de1 < t.length)
               {
                       de2 = de1 + sortLength;
                       de3 = de2 + sortLength;
                       if(de2>t.length) de2 = t.length;
                       if(de3>t.length) de3 = t.length;
                       tmp = fusion(t, tmp, de1, de2-1, de2, de3-1, de3-de1, de1, sortColumn, sortOrder);
                       de1 = de3;
               }
 
               for(i = 0 ; i < t.length ; i++)
                       t[i] = tmp[i];
               
               sortLength *= 2;
       }
       return t;
}

function afficher( s ){
    s += "\n[\n";
    for(var i = 0; i < fiches_array.length; i++){
        s += "    " + i + "={\n";
            s+="        marque: " + fiches_array[i][1] + ",\n";
            s+="        modele: " + fiches_array[i][2] + ",\n";
        s += "    }";
        if(i  < fiches_array.length - 1)
            s+=",\n";
    }
    s += "\n]";
    alert(s);
}

add_array("http://www.dpm-motors.com/","ASTON MARTIN","Vanquish S","","Noir","12 000","Cuir noir","2005","08/09/2005","","220 000 EUR","Aston5859.JPG|Aston5859A.JPG|Aston5859B.JPG");
add_array("http://www.dpm-motors.com/","AUDI","A3 1,8 L Turbo Quattro","","Bleu","63 036","Cuir beige","2003","06/01/2003","PDC, CD, 5P.Ambiente","14 800 EUR","AUDIA5678.JPG");

//On lance le tri
triFusion(fiches_array, "modele", 1); // Tri ascendant
afficher("Tri ascendant modele");
triFusion(fiches_array, "modele", -1); // Tri descendant
afficher("Tri descendant modele");

triFusion(fiches_array, "marque", 1); // Tri ascendant
afficher("Tri ascendant marque");
triFusion(fiches_array, "marque", -1); // Tri descendant
afficher("Tri descendant marque");
-->
</script>

</head>

</html>
Messages postés
440
Date d'inscription
mardi 21 octobre 2003
Statut
Membre
Dernière intervention
6 mai 2010
1
Salut à tous,

En effet c'est pour de la prod, je te remercie, je vais voir ca 2m1, une chose qui m'étonne c'est qu'on est obligé de faire une fonction, nous même, et que ca n'existe pas une toute prête comme sort(), qui existe déjà!!!!

Merci je vais regarder ca serieusement 2m1
Messages postés
177
Date d'inscription
jeudi 5 octobre 2006
Statut
Membre
Dernière intervention
16 janvier 2009
1
Bonjour,
une idée intérressante serait de proposer une source qui ajoute une méthode à la classe Array de tri qui prendrai une fonction de comparaison en paramètre.
Du genre :
Array.prototype.sortAs = function( compareFunction ){
    //Une boucle de tri
       // Un test avec appel de la fonction de comparaison
       if( compareFunction( o1, o2) < 0 )
             //Inversion ou fusion
}
Cordialement,
Pierrick
Messages postés
177
Date d'inscription
jeudi 5 octobre 2006
Statut
Membre
Dernière intervention
16 janvier 2009
1
A noter,
J'ai rarement vu des tri en javascript coté client...
La raison est simple, souvent le client n'a accès qu'à une portion de la collection pour cause de rapidité.
Le tri est fait coté serveur, d'ailleurs souvent en SQL.
Une solution sympas est le Rico Live Grid qui gère cela très bien en ajax en plus.
Cordialement,
Pierrick
Messages postés
1044
Date d'inscription
lundi 7 mars 2005
Statut
Membre
Dernière intervention
13 juillet 2010
7
the_wwt -> Tu veux dire quelque chose comme ça ?

["test","123","nmjj","free","!@","dddd"].sort(function (element1,element2){
if (element1 < element2)
{
return -1;
}
if (element1 == element2)
{
return 0;
}
if (element1 > element2)
{
return 1;
}
});
Messages postés
440
Date d'inscription
mardi 21 octobre 2003
Statut
Membre
Dernière intervention
6 mai 2010
1
Salut à tous,

Bah en fait ce n'est pas possible de faire des requete SQL car c'est un site qui va réferencer 5 sites d'annonces automobiles différents j'ai donc crée 5 fichiers XML (sur chacun des sites) et donc là j'ai tout rappatrié dans mon tableau qui est en javascript, mais pour trier ma liste je n'ai pas de problème, en effet je me sert de DOM, par contre j'ai besoin de faire des champ (via le control select) ou je rappatrie mes marque dans le champ marque alphabetiquement et modele dans le champ modele alphabetiquement aussi...

Merci d'avance
Messages postés
177
Date d'inscription
jeudi 5 octobre 2006
Statut
Membre
Dernière intervention
16 janvier 2009
1
Bonjour,
[auteurdetail.aspx?ID=463723 Arto_8000] -> Oui tout a fait, je ne pense pas qu'elle existe... me trompai-je?
[auteurdetail.aspx?ID=182650 ludovicanceaux] -> Bon et bien par sur cette solution en javascript...
Je te fais le bout de code pour étendre la classe Array, si ça intéresse quelqu'un...
Cordialement,
Pierrick
Messages postés
177
Date d'inscription
jeudi 5 octobre 2006
Statut
Membre
Dernière intervention
16 janvier 2009
1
Re...
Ok merci Arto_8000, je ne connaissai pas cette fonction...
Bien voilà, tu as ta réponse ludovicanceaux.
Cordialement,
Messages postés
13616
Date d'inscription
jeudi 13 février 2003
Statut
Membre
Dernière intervention
15 octobre 2013
36
Bonjour,

    autres pistes ?

    _ si tu n'as que 2 colonnes, inverse les avant de faire le sort.

    _ si les donnnées sont dans du xml, pourquoi ne pas utiliser le xsl ?
          qui lui fera tri sur ce que tu veux, comme tu le veux.

    _ j'ai mis un ch'tit script qui tri directement les colonnes html
          http://www.javascriptfr.com/codes/TRI-MULTI-COLONNES-TABLEAU-HTML_30425.aspx

<hr />


Cordialement                Bul    
Messages postés
440
Date d'inscription
mardi 21 octobre 2003
Statut
Membre
Dernière intervention
6 mai 2010
1
Salut à tous,

je te remercie bultez, en fait j'utilise déjà ton code pour trier mon tableau par colonne mais ton code ne marcherais pas par hasard que pour les tableau qui sont écrit en dur????
car moi en fait finalement je veux juste trier ma combobox en fait, finalement, j'ai essayé de faire un truc ca à l'air de marche, cependant je ne suis pas sur que ce soit si fiable!!!!
function add_filter_advance_input(control,num_colonne){
  var array_tmp=new Array;
  for(i=0;i<fiches_array.length;i++){
   array_tmp[i]=fiches_array[i][num_colonne];
  }
  array_tmp.sort();
  var double=false;
  for(var i=0;i<array_tmp.length;i++){
   double=false;
   for(n=0;n<control.length;n++){
    if(control[n].value==array_tmp[i]){
     double=true;
    }
   }
   if(double==false){
    nouvel_element=new Option(array_tmp[i],array_tmp[i],false,false);
    control.options[control.length]=nouvel_element;
   }
  }
  compte_nbr_auto();
 }
Messages postés
440
Date d'inscription
mardi 21 octobre 2003
Statut
Membre
Dernière intervention
6 mai 2010
1
Salut à tous,

En fait, c'est en lisant ta réponse "si tu n'as que 2 colonnes, inverse les avant de faire le sort." que j'ai eu l'idée.
Maintenant le script de comparaison écrite en haut, je le met de coté car ca m'interresse, je suis en train de me documenter sur les fonctions utilisés!!! car il faut que la recherche avancé fonctionne avec tous les champs, dur, dur lol
Messages postés
13616
Date d'inscription
jeudi 13 février 2003
Statut
Membre
Dernière intervention
15 octobre 2013
36
>>mais ton code ne marcherais pas par hasard que pour les tableau qui sont écrit en dur????
    ben.. c'est pour trier des colonnes dans <table> en html.
    c'est donc toujours en dur ( même si php,xml... ont servi pour le générer )


>>je veux juste trier ma combobox
    ah... un <select> ?   pas <table> ?
    adapter les réponses   au cas particulier d'un select.

<hr />
Cordialement                Bul    
Messages postés
177
Date d'inscription
jeudi 5 octobre 2006
Statut
Membre
Dernière intervention
16 janvier 2009
1
Bonjour messieurs,
Euh si ça peut intéréssé quelqu'un, j'ai ajouté des méthodes de tri à la classe Array et je me suis apperçu que la dernière ( le tri shell) est six fois plus rapide sous IE que la fonction native.
En revanche sous FF, rien à faire la fonction native sort est la meilleure.
Je sais que c'est pas le lieu pour balancer tout ce code mais bon, je ne vais pas déposer une source pour ça.
En plus rien d'intérréssant en terme d'algos, ils sont tous sous wikipedia.
Mais bon si bultez (ou autres) n'est pas content, il me grondera.... et enlèvera.
Si ça peut t'aider,
cordialement,
Pierrick
 <---------------------------------------------------------------------------------------------------------->
<html>
<head>
<title></title>
</head>

<script language="javascript" type="text/javascript">
<!--
Array.prototype.sortF = function( cf ){
    var sortLength = 1, de1, de2, de3, i;
    this.tmp = [];
    this.cf = typeof cf != 'undefined' ? cf : function (e1,e2){ return e1 < e2 ? -1 : e1 == e2 ? 0 : 1; };
    while(sortLength < this.length)
    {
        de1 = 0;
        while(de1 < this.length)
        {
                de2 = de1 + sortLength;
                de3 = de2 + sortLength;
                if(de2>this.length) de2 = this.length;
                if(de3>this.length) de3 = this.length;
               
                this._fusion(de1, de2-1, de2, de3-1, de3-de1, de1);
                de1 = de3;
        }
 
        for(i = 0 ; i < this.length ; i++){
             this[i] = this.tmp[i];
        }
       
        sortLength *= 2;
    }
    return this;
};

Array.prototype._fusion = function(de1, vers1, de2, vers2, count, posInB)
{
       for(var j = 0 ; j < count ; j++)
       {
               if(de2 > vers2)
                       this.tmp[posInB++] = this[de1++];
               else if(de1 > vers1)
                       this.tmp[posInB++] = this[de2++];
               else if(this.cf(this[de1], this[de2]) < 0)
                       this.tmp[posInB++] = this[de1++];
               else
                       this.tmp[posInB++] = this[de2++];
       }
}

Array.prototype.sortQ = function(cf, p, r) {
    var q;
    if( this.cf == null )
        this.cf = typeof cf != 'undefined' ? cf : function (e1,e2){ return e1 < e2 ? -1 : e1 == e2 ? 0 : 1; };
    if( typeof p == 'undefined' )
        p = 0;
    if( typeof r == 'undefined' )
        r = this.length;
    if(p<r) {
            q = this._part(p, r);
            this.sortQ(null, p, q);
            this.sortQ(null, q+1, r);
    }
}
 
Array.prototype._part = function(p, r) {    var pivot this[p], i p-1, j = r+1;
    var temp;
    while(true) {
            do
                    j--;
            while(this.cf( this[j], pivot) > 0);
            do
                    i++;
            while(this.cf( this[i], pivot) < 0);
            if(i<j) {
                    temp = this[i];
                    this[i] = this[j];
                    this[j] = temp;
            }
            else
              return j;
    }
    return j;
}

Array.prototype.sortS = function( cf ) {
    this.cf = typeof cf != 'undefined' ? cf : function (e1,e2){ return e1 < e2 ? -1 : e1 == e2 ? 0 : 1; };
    /*
     * gaps[] doit approximer une Série géométrique.
     * La sequence suivante est la meilleure connue en terme
     * de nombre moyen de comparaisons. voir:
     * http://www.research.att.com/~njas/sequences/A102549
     */
    var gaps = [ 1, 4, 10, 23, 57, 132, 301, 701 ];
  
    for(var sizeIndex = gaps.length - 1; sizeIndex >= 0; --sizeIndex){
           var gap = gaps[ sizeIndex ];
        for (var i = gap; i < this.length; ++i) {
            var value = this[i];
            for (var j = i - gap; j >= 0 && this.cf(this[j], value) > 0; j -= gap) {
                this[j + gap] = this[j];
            }
            this[j + gap] = value;
        }          
    }
}

function afficher(title, table){
    var s = "" + title + "=[
&nbsp;&nbsp;&nbsp;&nbsp;";
    for( var i = 0; i < table.length; i++){
        s += table[i];
        if( i < table.length - 1)
            s += ",";
        if( i % 10 == 0 && i > 0)
            s += "
&nbsp;&nbsp;&nbsp;&nbsp;";
    }
    s += "
]

";
    document.body.innerHTML += s;
}
var cf function (element1,element2){ return element1 < element2 ? -1 : element1 element2 ? 0 : 1; }

var table = [];

for( var i = 0; i < 1000; i++)
    table[i] = parseInt( Math.random() * 1000 );

var start1 = new Date();

table.sort( cf );
var end1 = new Date();
afficher( "Sort native: ", table );

table = [];

for( var i = 0; i < 1000; i++)
    table[i] = parseInt( Math.random() * 1000 );
var start2 = new Date();

table.sortF( cf );

var end2 = new Date();
afficher( "Sort fusion: ", table );

table = [];

for( var i = 0; i < 1000; i++)
    table[i] = parseInt( Math.random() * 1000 );
var start3 = new Date();

table.sortQ( cf );

var end3 = new Date();
afficher( "Sort rapide: ", table );

table = [];

for( var i = 0; i < 1000; i++)
    table[i] = parseInt( Math.random() * 1000 );
var start4 = new Date();

table.sortS( cf );

var end4 = new Date();
afficher( "Sort shell: ", table );

alert( " sort: " + ( end1 - start1 ) + "ms\n sortF: " + ( end2 - start2 ) + "ms\n sortQ: " + ( end3 - start3 ) + "ms\n sortS: " + ( end4 - start4 ) + "ms");

-->
</script>

</html>
Messages postés
13616
Date d'inscription
jeudi 13 février 2003
Statut
Membre
Dernière intervention
15 octobre 2013
36
>>si bultez n'est pas content,
    pourquoi ne le serais-je pas ?
    en quoi cela me regarderait-il ?

>>il me grondera....
    de quel droit ferais-je ça ? pas trop mon genre.

>>et enlèvera.
    pas plus de pouvoir que toi à ce niveau là.

>>Si ça peut t'aider,
    ce serait d'ailleurs assez mal venu de faire une remarque
        sur un exemple posté pour aider !
        et qui plus est, intéressant.
        peut-être pas une source, mais au moins un snippet.

    je rale parfois, et ça m'engage que moi, essentiellement sur 2 aspects :
    _ les "offres d'embauche", les demandes de développements... gratis.
    _ les critiques sans fondement, le dénigrement gratuit...  de tel ou tel produit,soft...





<hr />



Cordialement            Bul    
Messages postés
177
Date d'inscription
jeudi 5 octobre 2006
Statut
Membre
Dernière intervention
16 janvier 2009
1
Bonjour,
Bultez: je pense que tu as compris que c'était une note d'humour... :p
            De plus je ne t'ai, en effet, jamais vu faire ce genre de faits, c'est vrai.
J'ajoute que j'ai finis par déposer une source sur les tris, car j'ai ajouté des test graphqiues permettant de voire l'efficacité des algos en fonction du type de collection.
Bien cordialement et bonne journée.
Pierrick
Messages postés
13616
Date d'inscription
jeudi 13 février 2003
Statut
Membre
Dernière intervention
15 octobre 2013
36
>>c'était une note d'humour
    sur ce coup là, je pensais que tu étais sérieux...

>>je ne t'ai, en effet, jamais vu faire ce genre de faits
    ouf...
    parfois les comportements peuvent préter à confusion,
    ravi que le mien ne te donne pas ce genre d'impression.

>>J'ajoute que j'ai fini par déposer une source
    tu as bien fait ( à mon humble avis ).






<hr />



Cordialement                Bul        
Messages postés
440
Date d'inscription
mardi 21 octobre 2003
Statut
Membre
Dernière intervention
6 mai 2010
1
Salut à tous,

Dis moi The WWT, je me suis interressé de près à ta fonction écrite plus haut, c pourquoi il y a 2 semaines qui se sont écoulées depuis (lol ;-)), mais dans ta fonction compare:
function compareObjet(o1, o2, sortColumn, sortOrder){
    if( sortColumn == "modele"){
        return sortOrder > 0 ? o1[2] < o2[2] : o1[2] > o2[2];
    }else{
        return sortOrder > 0 ? o1[1] < o2[1] : o1[1] > o2[1];
    }
}

ca c'est si on veux trier par modele, mais si on veux trier par marque, il faut faire je suppose:
function compareObjet(o1, o2, sortColumn, sortOrder){
    if( sortColumn == "marque"){
        return sortOrder > 0 ? o1[2] < o2[2] : o1[2] > o2[2];
    }else{
        return sortOrder > 0 ? o1[1] < o2[1] : o1[1] > o2[1];
    }
}

si c'est ca je suppose que je pe passer ca dans une fonction:
function compareObjet(o1, o2, sortColumn, sortOrder,type){
    if( sortColumn == type){
        return sortOrder > 0 ? o1[2] < o2[2] : o1[2] > o2[2];
    }else{
        return sortOrder > 0 ? o1[1] < o2[1] : o1[1] > o2[1];
    }
}
si tu peux me dire si mon raisonneent est juste, ca serait cool, Merci d'avance
Messages postés
177
Date d'inscription
jeudi 5 octobre 2006
Statut
Membre
Dernière intervention
16 janvier 2009
1
Bonjour,
non en fait cette fonction c'était pour l'algo de tri que je t'ai donné. Dans le même esprit avec la fonction native du browser sort().
Tu n'as qu'a déclarer deux variables globales: type et ordre.
Ensuite dans ta fonction de comparaison tu lit ces variables:

var type = "marque";
var ordre = 1;

function comparaison(e1, e2){
    if( type == "marque")
        return ordre > 0 ? e1[2] < e2[2] ? - 1 : e1[2] > e2[2] ? 1 : 0;
    else if( type == "modele" )
       return ordre > 0 ? e1[3] < e2[3] ? - 1 : e1[3] > e2[3] ? 1 : 0;
   else if( type == "un autre attribut" )
    .....
   else
        return 0;
}

//Quand tu veux changer l'ordre du tri tu change les deux variables globales et tu appel ta fonction de tri avec la fonction de comparaison
type = "modele";
ordre = -1;
var table = [];
table.sort( comparaison );

/****/
Voilà pour le coup de pouce,
Cordialement,
Pierrick