Forcer un tri imposé sur un array

muqaddarmuqaddar Administrateur
16:58 modifié dans Objective-C, Swift, C, C++ #1
Hello,

Je cherche à  imposer un tri sur le contenu d'une clé d'un array.
Donc ce tri n'est pas alphabétique, ni numérique.

L'ordre sur le contenu de la clé serait G, K, B, D.

Est-il possible de faire cela avec les sort descriptors ? (sous-classe ? , méthode compareObject:toObject: ?)

Réponses

  • AliGatorAliGator Membre, Modérateur
    mai 2011 modifié #2
    Pour iOS4/OSX6 (donc si les blocs sont disponibles) :
    NSArray* sortedArray = [unsortedArray sortedArrayUsingComparator:^(id obj1, id obj2) {<br />&nbsp; NSArray* keysOrder = [NSArray arrayWithObjects:@&quot;G&quot;,@&quot;K&quot;,@&quot;B&quot;,@&quot;D&quot;,nil];<br />&nbsp; NSUInteger idx1 = [keysOrder indexOfObject:[obj1 yourKey]];<br />&nbsp; NSUInteger idx2 = [keysOrder indexOfObject:[obj2 yourKey]];<br />&nbsp; return (idx1&lt;idx2) ? NSOrderedAscending : (idx1&gt;idx2) ? NSOrderedDescending : NSOrderedSame;<br />}];
    
    Si tu dois être compatible pré-iOS4 et pré-OSX6, tu peux faire la même chose en passant un @selector en paramètre dans lequel tu mettras le code du block. Du coup le code est ailleurs c'est moins lisible, et c'est moins sexy qu'avec les blocks, mais bon.

    Après le mieux c'est peut-être plutôt de prévoir, dans les objets que tu veux comparer, une méthode "compare:", qui est la méthode appelée lors des comparaisons par défaut (par exemple avec un NSSortDescriptor c'est la méthode "compare:" qui est appelé sur les objets à  comparer pour savoir dans quel ordre les trier l'un par rapport à  l'autre). Du coup dans cette méthode "-compare:" de tes objets tu mets le code que j'ai mis dans le block au dessus (enfin qui prendre que obj2 en paramètre, obj1 correspondant dans ce cas à  l'objet "self"). Et du coup tu feras les comparaison normalement, avec un NSSortDescriptor assez classique du coup, et c'est ta classe qui sait comment faire la comparaison entre 2 instances.
  • muqaddarmuqaddar Administrateur
    16:58 modifié #3
    Salut Ali,

    En fait, l'application est > iOS 4 donc c'est bon pour les blocks.

    Je m'accroche sur ton code, mais j'ai un autre soucis : en fait j'ai besoin de trier avec 2 descripteurs:
    - le premier sur une clé, dont l'ordre est imposé comme tu l'as montré brillamment (avec les blocks donc par exemple)
    - le deuxième classique (ordre alpha sur une autre clé)

    Il s'agit donc de fusionner les 2 sans encombre (alliance de la vieille technique et de la nouvelle ou bien on peut le faire qu'avec les blocks aussi ?). J'ai beau relire ton paragraphe, et même avec une méthode compare:, je sèche un peu dans quel ordre il faut faire les choses.

  • AliGatorAliGator Membre, Modérateur
    mai 2011 modifié #4
    Alors du coup au lieu d'utiliser directement [tt]sortedArrayUsingComparator[/tt] (un NSComparator étant ce fameux block retournant un enum NSOrderedMachin), il te suffit d'utiliser [tt]sortedArrayUsingSortDescriptors[/tt], et pour ton premier sort-descriptor tu utilises un NSSortDescriptor qui, lui, est défini avec le fameux NSComparator/block.

    Autrement dit, tu crées un NSSortDescriptor en utilisant [tt]+ (id)sortDescriptorWithKey:(NSString *)key ascending:(BOOL)ascending comparator:(NSComparator)cmptr[/tt], en mettant comme NSComparator le code que j'ai plus plus haut dans le block (enfin s'il marche, je l'ai tapé direct dans le forum j'ai pas testé, je te laisse adapter au besoin).
    Et après bah tu fais comme d'habitude, tu utilises sortedArrayUsingDescriptors en passant un NSArray avec tes 2 sortdescriptors, celui-là  et le 2e classique pour ordre alpha sur ton autre clé.
  • DrakenDraken Membre
    16:58 modifié #5
    dans 1304356224:

    L'ordre sur le contenu de la clé serait K, G, B

    oO
  • muqaddarmuqaddar Administrateur
    16:58 modifié #6
    Bon, je crois que ça marche. :-)
    Ali, le roi des blocks.

    &nbsp; NSSortDescriptor *descriptor1 = [NSSortDescriptor sortDescriptorWithKey:@&quot;instrument&quot; ascending:YES comparator:^(id obj1, id obj2) {<br />&nbsp; &nbsp; NSArray *keysOrder = [NSArray arrayWithObjects:@&quot;G&quot;,@&quot;K&quot;,@&quot;B&quot;,@&quot;D&quot;,nil];<br />&nbsp; &nbsp; NSUInteger idx1 = [keysOrder indexOfObject:obj1];<br />&nbsp; &nbsp; NSUInteger idx2 = [keysOrder indexOfObject:obj2];<br />&nbsp; &nbsp; return (idx1&lt;idx2) ? NSOrderedAscending : (idx1&gt;idx2) ? NSOrderedDescending : NSOrderedSame;<br />&nbsp; }];<br />	NSSortDescriptor *descriptor2 = [NSSortDescriptor sortDescriptorWithKey:@&quot;title&quot; ascending:YES];<br /><br />	return [items sortedArrayUsingDescriptors:[NSArray arrayWithObjects:descriptor1, descriptor2, nil]];
    
Connectez-vous ou Inscrivez-vous pour répondre.