[GM8.1 / GML] Tri de plusieurs listes en fonction d'une autre

Démarré par Arca, 16 Juin 2014 à 22:30

0 Membres et 1 Invité sur ce sujet

16 Juin 2014 à 22:30 Dernière édition: 16 Juin 2014 à 22:32 par iArcadia
Bonsoir chers solarussiens.

Me voilà en présence d'un problème qui est relativement embêtant. Ce n'est pas faute d'avoir essayé plusieurs méthodes, il m'est arrivé de penser avoir trouver la bonne, mais il s'avère un peu plus tard que ce n'est pas le cas quand j'ajoute du contenu.

Voici concrètement ce que je voudrais réaliser : une sorte de "Pokédex" pour ranger les différents dragons disponibles du jeu facebook Dragon City. Seulement voilà, impossible d'associer les informations affichées à l'écran avec le dragon concerné.

Pour être un peu plus précis, je copie la liste contenant le nom des dragons (global.dragonName) dans une liste temporaire (tempList), puis je trie global.dragonName dans l'ordre alphabétique grâce à une fonction de base (ds_list_sort), et j'essaye de trier toutes les autres en récupérant le nouvel index de la liste triée... Enfin en gros, un p'tit bordel.

Je vous passe la fonction que j'ai créé au cas où, vu comment j'explique super bien.

var tempList, i, tempValue, tempIndex; // déclaration de variables

// copie de la liste contenant le nom des dragons dans une liste temporaire
tempList = ds_list_create();
ds_list_copy(tempList,global.dragonName);

// tri de la liste d'origine dans l'ordre alphabetique
ds_list_sort(global.dragonName,argument0);

// parcourt de toutes les autres listes
for (i = 0 ; i <= (ds_list_size(tempList)-1) ; i += 1) // tant que i est inférieur à la taille de la liste (= du nombre total de dragons)
{    
   // récupère le nouvel index grâce à la valeur de la liste temporaire
   tempValue = ds_list_find_value(tempList,i);
   tempIndex = ds_list_find_index(global.dragonName,tempValue);
   
   // déplace les informations de l'index d'origine vers le nouvel index pour chaque liste
   tempValue = ds_list_find_value(global.dragonPictureName,i);
   ds_list_insert(global.dragonPictureName,tempIndex,tempValue);
   if (i < tempIndex) ds_list_delete(global.dragonPictureName,i);
   else ds_list_delete(global.dragonPictureName,i+1);
   
   tempValue = ds_list_find_value(global.dragonDescription,i);
   ds_list_insert(global.dragonDescription,tempIndex,tempValue);
   if (i < tempIndex) ds_list_delete(global.dragonDescription,i);
   else ds_list_delete(global.dragonDescription,i+1);
   
   ... (y'en a plein d'autres !)
   
   tempValue = ds_list_find_value(tempList,i);
   ds_list_insert(tempList,tempIndex,tempValue);
   if (i < tempIndex) ds_list_delete(tempList,i);
   else ds_list_delete(tempList,i+1);
}


Si vous ne comprenez pas le problème, n'hésitez pas à me le dire que j'explique un peu mieux ! :)
Anciennement iArcadia / Zora Rouge

La solution la plus simple serait de :
- Copier la liste des noms
- La trier dans l'ordre souhaité
- Garder cette copie

Et pour accéder aux informations :
- Récupérer l'index du dragon dans la liste d'origine grâce à son nom
- Récupérer les informations du dragon via cet index

Idéalement, la liste "triée" devrait même contenir directement les index dans la liste d'origine :p

Ah tiens tu n'es pas porté disparu toi ? :)

Merci pour ta réponse, mais ce que tu viens d'expliquer, je crois que ça correspond à ce que je fais en fait :

Citation- Récupérer l'index du dragon dans la liste d'origine grâce à son nom

tempValue = ds_list_find_value(tempList,i);
tempIndex = ds_list_find_index(global.dragonName,tempValue);


Ou alors je n'ai pas compris ta solution.
Anciennement iArcadia / Zora Rouge

Je parlais plutôt de récupérer l'index à partir du nom lors de l'affichage des informations, et les récupérer a ce moment là, plutôt que de trier toutes les différentes listes ^^

Ca remonte tout ça ^^'

Bon alors déjà une première chose: il est délicat de modifier une liste pendant qu'on la parcourt (on risque de modifier les infos dont on aura besoin lors d'une itération ultérieure).

Ensuite, c'est plutôt lourd de trier plusieurs listes (perfs), alors qu'une seule suffirait. Si tu tiens absolument à garder plusieurs listes, pourquoi ne pas simplement créer une liste de positions et t'arranger pour maintenant la correspondance élément à élément avec la liste qui te sert d'ordre (alphabêtique en l'occurence). Ce qui te fait deux listes à réorganiser. Ensuite, tu parcours les éléments de la liste à positions et tu les utilises comme position pour récupérer les éléments depuis les autres listes (que tu n'as plus besoin de trier).

EDIT1: c'est la solution postée par Néo2 entre-temps :P
EDIT2: surtout que récupérer un élément par sa valeur est beaucoup plus coûteux que par sa position. (pour ceux qui me gueuleraient dessus, sachez que les listes Gml sont implémentées par des tableaux).

Sinon, je me demande s'il n'y a pas moyen de grouper toutes les infos relatives aux dragons dans un type d'objet et de créer une liste d'instances vers ces objets. Ainsi, tu n'as qu'une seule liste. Mais ça ne t'arrange pas pour le tri vu que tu ne disposes que de deux tris: croissant et décroissant qui se fera sur les id d'instance dans le cas présent :/

La meilleure solution que je vois passerait par une dll faite maison (un langage tel que le C permet de grouper toutes les données des dragons au sein d'une même structure et de trier selon l'une des caractéristiques via callback comparateur).

En fait, tout dépend du nombre d'ordre de tri que tu aimerais. Si tu ne veux qu'un tri alphabêtique en plus de l'ordre par défaut (id spécifique aux dragons commençant à 0 jusque ton nombre de dragons-1), alors je te conseille de passer par un conteneur map (nomDuDragon->idDuDragon). Je m'explique:
A) création des structures de données

  • A1) Tu crées un tableau global pour chaque caractéristique du dragon (sauf le nom), et tu les insères dans l'ordre d'id des dragons. Par exemple
    img[0] = imgBulbizarre, img[1] = imgHerbizarre, ...
    type[0] = plante, type[1] = plante, ...
  • A2) tu crées une liste avec les noms de tes dragons
    ds_list_add(nameList, "bulbizarre"), ds_list_add(nameList, "herbizarre"),  ...
  • A3) tu crées une map avec comme clef le nom du dragon et comme valeur associée l'id du dragon
    ds_map_add(map, "bulbizarre", 0), ds_map_add(map, "herbizarre", 1), ...
B ) Tri par id

  • B1) par ordre croissant, il te suffit de parcourir tous les tableaux d'un coup avec un index allant de 0 jusque nombreDeDragon-1 (une seule boucle for dans laquelle tu accèdes à l'élément i de toutes tes listes)
  • B2) par ordre décroissant, idem, mais de nombreDeDragons-1 à 0.
C) Tri par ordre alphabêtique (croissant comme décroissant)

  • C1) tu tries la liste par ordre alphabêtique (croissant ou décroissant) : ds_list_sort(nameList, true)
  • C2) tu parcours cette liste dans l'ordre et tu récupère le nom : name = ds_list_find_value(nameList, i)
  • C3) tu utilise le nom dans la map pour récupérer l'id : id = ds_map_find_value(map, name)
  • C4) tu utilises l'id dans chacun de tes tableaux pour récupérer l'élément associé : value = img[id], type = img[id], ...

Ca devrait fonctionner à condition que le conteneur map accepte le texte comme clef.
Si tu veux trier par type, ça sert à rien d'utiliser un conteneur map puisque plante correspond à plusieurs Pokémon --> lequel choisir ? En fait, la relation caractéristique <-> id doit être bijective :)
Marre des pavés ? Marchez dans la boue!
ハハ、あなたは私の罠に落ちた!