Comment trier un NSMutableArray contenant des objets personnalisés?

1268

Ce que je veux faire semble assez simple, mais je ne trouve aucune réponse sur le Web. J'ai un NSMutableArraydes objets, et disons que ce sont des objets «personne». Je veux trier le NSMutableArraypar Person.birthDate qui est un NSDate.

Je pense que cela a quelque chose à voir avec cette méthode:

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(???)];

En Java, je ferais en sorte que mon objet implémente Comparable, ou utiliserais Collections.sort avec un comparateur personnalisé en ligne ... comment diable faites-vous cela dans Objective-C?

rustyshelf
la source

Réponses:

2299

Méthode de comparaison

Soit vous implémentez une méthode de comparaison pour votre objet:

- (NSComparisonResult)compare:(Person *)otherObject {
    return [self.birthDate compare:otherObject.birthDate];
}

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(compare:)];

NSSortDescriptor (meilleur)

ou encore mieux:

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                           ascending:YES];
NSArray *sortedArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];

Vous pouvez facilement trier par plusieurs clés en en ajoutant plusieurs au tableau. L'utilisation de méthodes de comparaison personnalisées est également possible. Jetez un œil à la documentation .

Blocs (brillants!)

Il y a aussi la possibilité de trier avec un bloc depuis Mac OS X 10.6 et iOS 4:

NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
    NSDate *first = [(Person*)a birthDate];
    NSDate *second = [(Person*)b birthDate];
    return [first compare:second];
}];

Performance

Les -compare:méthodes basées sur des blocs seront un peu plus rapides, en général, que leur utilisation NSSortDescriptorcar cette dernière repose sur KVC. Le principal avantage de la NSSortDescriptorméthode est qu'elle fournit un moyen de définir votre ordre de tri en utilisant des données, plutôt que du code, ce qui facilite par exemple la configuration des choses afin que les utilisateurs puissent trier un NSTableViewen cliquant sur la ligne d'en-tête.

Georg Schölly
la source
66
Le premier exemple a un bogue: vous comparez la variable d'instance birthDate dans un objet avec l'autre objet lui-même, plutôt que sa variable birthDate.
Martin Gjaldbaek
90
@Martin: Merci! C'est drôle que personne d'autre ne l'ait remarqué avant que j'obtienne 75 votes positifs.
Georg Schölly
76
Parce que c'est la réponse acceptée, et donc probablement considérée comme définitive par la plupart des utilisateurs, il pourrait être utile d'ajouter un 3e exemple basé sur des blocs afin que les utilisateurs sachent qu'il existe également.
jpswain
6
@ orange80: J'ai essayé ça. Je ne possède plus de Mac, donc ce serait bien si vous pouviez regarder le code.
Georg Schölly
11
Si vous en avez un, NSMutableArrayje préfère utiliser les méthodes sortUsingDescriptors, sortUsingFunctionou sortUsingSelector. Dans la mesure où le tableau est modifiable, je n'ai généralement pas besoin d'une copie triée.
Stephan
109

Voir la NSMutableArrayméthodesortUsingFunction:context:

Vous devrez configurer une fonction de comparaison qui prend deux objets (de type Person, car vous comparez deux Personobjets) et un paramètre de contexte .

Les deux objets ne sont que des instances de Person. Le troisième objet est une chaîne, par exemple @ "birthDate".

Cette fonction renvoie un NSComparisonResult: Elle renvoie NSOrderedAscendingsi PersonA.birthDate< PersonB.birthDate. Il reviendra NSOrderedDescendingsi PersonA.birthDate> PersonB.birthDate. Enfin, il retournera NSOrderedSamesi PersonA.birthDate== PersonB.birthDate.

C'est un pseudocode grossier; vous devrez préciser ce que signifie qu'une date soit "moins", "plus" ou "égale" à une autre date (par exemple, en comparant les secondes depuis l'époque, etc.):

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  if ([firstPerson birthDate] < [secondPerson birthDate])
    return NSOrderedAscending;
  else if ([firstPerson birthDate] > [secondPerson birthDate])
    return NSOrderedDescending;
  else 
    return NSOrderedSame;
}

Si vous voulez quelque chose de plus compact, vous pouvez utiliser des opérateurs ternaires:

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  return ([firstPerson birthDate] < [secondPerson birthDate]) ? NSOrderedAscending : ([firstPerson birthDate] > [secondPerson birthDate]) ? NSOrderedDescending : NSOrderedSame;
}

L'intégration pourrait peut-être accélérer un peu cela, si vous le faites souvent.

Alex Reynolds
la source
9
Utiliser sortUsingFunction: context: est probablement le moyen le plus c-ish et certainement le plus illisible.
Georg Schölly
12
Il n'y a rien de mal à cela, mais je pense qu'il existe maintenant de bien meilleures alternatives.
Georg Schölly
6
Peut-être, mais je ne pense pas que ce serait moins lisible pour quelqu'un d'origine Java qui pourrait rechercher quelque chose de similaire à la classe Comparator abstraite de Java, qui implémente compare (Type obj1, Type obj2).
Alex Reynolds
5
J'ai l'impression que certains d'entre vous recherchent une raison quelconque de critiquer cette réponse parfaitement correcte, même si cette critique a très peu de valeur technique. Bizarre.
Alex Reynolds,
1
@Yar: Soit vous pouvez utiliser la solution que j'ai fournie dans le premier paragraphe, soit vous utilisez plusieurs descripteurs de tri. sortedArrayUsingDescriptors: prend un tableau de descripteurs de tri comme argument.
Georg Schölly
62

Je l'ai fait dans iOS 4 en utilisant un bloc. J'ai dû convertir les éléments de mon tableau d'id en mon type de classe. Dans ce cas, il s'agissait d'une classe appelée Score avec une propriété appelée points.

Vous devez également décider quoi faire si les éléments de votre tableau ne sont pas du bon type, pour cet exemple, je viens de revenir NSOrderedSame, mais dans mon code, j'ai cependant une exception.

NSArray *sorted = [_scores sortedArrayUsingComparator:^(id obj1, id obj2){
    if ([obj1 isKindOfClass:[Score class]] && [obj2 isKindOfClass:[Score class]]) {
        Score *s1 = obj1;
        Score *s2 = obj2;

        if (s1.points > s2.points) {
            return (NSComparisonResult)NSOrderedAscending;
        } else if (s1.points < s2.points) {
            return (NSComparisonResult)NSOrderedDescending;
        }
    }

    // TODO: default is the same?
    return (NSComparisonResult)NSOrderedSame;
}];

return sorted;

PS: c'est le tri par ordre décroissant.

Chris
la source
6
Vous n'avez pas réellement besoin des transtypages "(Score *)", vous pouvez simplement faire "Score * s1 = obj1;" car id sera joliment casté vers n'importe quoi sans avertissement du compilateur :-)
jpswain
right orange80 downcastingne nécessite pas de transtypage avant la variable faible.
thesummersign
Vous devez toujours trier néant et non nul en haut ou en bas, afin que le retour final par défaut soitreturn ((!obj1 && !obj2) ? NSOrderedSame : (obj1 ? NSOrderedAscending : NSOrderedDescending))
Scott Corscadden
heh Chris, j'ai essayé ce code, je fais un rafraîchissement dans mon programme .. pour la première fois je fais un travail correct, j'ai obtenu un ordre décroissant de sortie .. mais quand je rafraîchis. (exécute le même code avec les mêmes données) il a changé l'ordre, il ne descendait pas. Disons que je hv 4 objets dans mon tableau, 3 hv mêmes données, 1 est différent.
Nikesh K
Si vous vous attendez à des objets qui ne sont pas de la classe "Score", vous devez les trier un peu plus attentivement. Sinon, vous avez une situation où autre == score1 <score2 == autre qui est incohérent et pourrait entraîner des problèmes. Vous pouvez renvoyer une valeur qui implique le tri des objets Score avant tous les autres objets, et tous les autres objets sont égaux les uns aux autres.
gnasher729
29

À partir d'iOS 4, vous pouvez également utiliser des blocs pour le tri.

Pour cet exemple particulier, je suppose que les objets de votre tableau ont une méthode "position", qui renvoie un NSInteger.

NSArray *arrayToSort = where ever you get the array from... ;
NSComparisonResult (^sortBlock)(id, id) = ^(id obj1, id obj2) 
{
    if ([obj1 position] > [obj2 position]) 
    { 
        return (NSComparisonResult)NSOrderedDescending;
    }
    if ([obj1 position] < [obj2 position]) 
    {
        return (NSComparisonResult)NSOrderedAscending;
    }
    return (NSComparisonResult)NSOrderedSame;
};
NSArray *sorted = [arrayToSort sortedArrayUsingComparator:sortBlock];

Remarque: le tableau "trié" sera publié automatiquement.

Léviathan
la source
26

J'ai tout essayé, mais cela a fonctionné pour moi. Dans une classe, j'ai une autre classe nommée " crimeScene", et je veux trier par une propriété de " crimeScene".

Ça fonctionne super bien:

NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"crimeScene.distance" ascending:YES];
[self.arrAnnotations sortUsingDescriptors:[NSArray arrayWithObject:sorter]];
Fernando Redondo
la source
21

Il manque une étape dans la deuxième réponse de Georg Schölly , mais cela fonctionne très bien.

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                              ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];

// a ajouté le 's' parce que du temps a été perdu lorsque j'ai copié et collé et qu'il a échoué sans le 's' dans sortedArrayUsingDescriptors

Manuel Spuhler
la source
L'appel de méthode est en fait "sortedArrayUsingDescriptors:", avec un 's' à la fin.
CIFilter
19
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate" ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];

Merci, ça marche bien ...

Hardik Darji
la source
17

Vos Personobjets doivent implémenter une méthode, par exemple celle compare:qui prend un autre Personobjet, et revenir en NSComparisonResultfonction de la relation entre les 2 objets.

Ensuite, vous appelleriez sortedArrayUsingSelector:avec @selector(compare:)et cela devrait être fait.

Il existe d'autres façons, mais pour autant que je sache, il n'y a pas d'équivalent Cocoa de l' Comparableinterface. L'utilisation sortedArrayUsingSelector:est probablement la façon la plus indolore de le faire.

espace libre
la source
9

Les blocs iOS 4 vous sauveront :)

featuresArray = [[unsortedFeaturesArray sortedArrayUsingComparator: ^(id a, id b)  
{
    DMSeatFeature *first = ( DMSeatFeature* ) a;
    DMSeatFeature *second = ( DMSeatFeature* ) b;

    if ( first.quality == second.quality )
        return NSOrderedSame;
    else
    {
        if ( eSeatQualityGreen  == m_seatQuality || eSeatQualityYellowGreen == m_seatQuality || eSeatQualityDefault  == m_seatQuality )
        {
            if ( first.quality < second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        }
        else // eSeatQualityRed || eSeatQualityYellow
        {
            if ( first.quality > second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        } 
    }
}] retain];

http://sokol8.blogspot.com/2011/04/sorting-nsarray-with-blocks.html un peu de description

Kostiantyn Sokolinskyi
la source
8

Pour NSMutableArray, utilisez la sortUsingSelectorméthode. Il trie sur place, sans créer de nouvelle instance.

DenTheMan
la source
Juste une mise à jour: moi aussi je cherchais quelque chose qui triait le tableau mutable en place, il existe maintenant des méthodes équivalentes "sortUsing" pour toutes les méthodes "sortedArrayUsing" à partir d'iOS 7. Telles que sortUsingComparator:.
jmathew
7

Vous pouvez utiliser la méthode générique suivante à votre fin. Cela devrait résoudre votre problème.

//Called method
-(NSMutableArray*)sortArrayList:(NSMutableArray*)arrDeviceList filterKeyName:(NSString*)sortKeyName ascending:(BOOL)isAscending{
    NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:sortKeyName ascending:isAscending];
    [arrDeviceList sortUsingDescriptors:[NSArray arrayWithObject:sorter]];
    return arrDeviceList;
}

//Calling method
[self sortArrayList:arrSomeList filterKeyName:@"anything like date,name etc" ascending:YES];
MD Aslam Ansari
la source
6

Si vous NSNumberstriez simplement un tableau de , vous pouvez les trier avec 1 appel:

[arrayToSort sortUsingSelector: @selector(compare:)];

Cela fonctionne car les objets du tableau ( NSNumberobjets) implémentent la méthode de comparaison. Vous pouvez faire la même chose pour les NSStringobjets, ou même pour un tableau d'objets de données personnalisés qui implémentent une méthode de comparaison.

Voici un exemple de code utilisant des blocs de comparaison. Il trie un tableau de dictionnaires où chaque dictionnaire inclut un nombre dans une clé "sort_key".

#define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
 ^(id obj1, id obj2) 
  {
  NSInteger value1 = [[obj1 objectForKey: SORT_KEY] intValue];
  NSInteger value2 = [[obj2 objectForKey: SORT_KEY] intValue];
  if (value1 > value2) 
{
  return (NSComparisonResult)NSOrderedDescending;
  }

  if (value1 < value2) 
{
  return (NSComparisonResult)NSOrderedAscending;
  }
    return (NSComparisonResult)NSOrderedSame;
 }];

Le code ci-dessus passe par le travail d'obtention d'une valeur entière pour chaque clé de tri et de leur comparaison, comme une illustration de la façon de le faire. Puisque les NSNumberobjets implémentent une méthode de comparaison, elle pourrait être réécrite beaucoup plus simplement:

 #define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
^(id obj1, id obj2) 
 {
  NSNumber* key1 = [obj1 objectForKey: SORT_KEY];
  NSNumber* key2 = [obj2 objectForKey: SORT_KEY];
  return [key1 compare: key2];
 }];

ou le corps du comparateur pourrait même être distillé jusqu'à 1 ligne:

  return [[obj1 objectForKey: SORT_KEY] compare: [obj2 objectForKey: SORT_KEY]];

J'ai tendance à préférer des instructions simples et de nombreuses variables temporaires car le code est plus facile à lire et à déboguer. Le compilateur optimise de toute façon les variables temporaires, il n'y a donc aucun avantage à la version tout-en-un.

Dinesh_
la source
5

J'ai créé une petite bibliothèque de méthodes de catégorie, appelée Linq to ObjectiveC , qui rend ce genre de chose plus facile. En utilisant la méthode de tri avec un sélecteur à clé, vous pouvez trier birthDatecomme suit:

NSArray* sortedByBirthDate = [input sort:^id(id person) {
    return [person birthDate];
}]
ColinE
la source
Vous devez l'appeler " LINQ to Objective-C ".
Peter Mortensen
5

Je viens de faire un tri à plusieurs niveaux en fonction des besoins personnalisés.

// trie les valeurs

    [arrItem sortUsingComparator:^NSComparisonResult (id a, id b){

    ItemDetail * itemA = (ItemDetail*)a;
    ItemDetail* itemB =(ItemDetail*)b;

    //item price are same
    if (itemA.m_price.m_selling== itemB.m_price.m_selling) {

        NSComparisonResult result=  [itemA.m_itemName compare:itemB.m_itemName];

        //if item names are same, then monogramminginfo has to come before the non monograme item
        if (result==NSOrderedSame) {

            if (itemA.m_monogrammingInfo) {
                return NSOrderedAscending;
            }else{
                return NSOrderedDescending;
            }
        }
        return result;
    }

    //asscending order
    return itemA.m_price.m_selling > itemB.m_price.m_selling;
}];

https://sites.google.com/site/greateindiaclub/mobil-apps/ios/multilevelsortinginiosobjectivec

Boobalan
la source
5

J'ai utilisé sortUsingFunction :: dans certains de mes projets:

int SortPlays(id a, id b, void* context)
{
    Play* p1 = a;
    Play* p2 = b;
    if (p1.score<p2.score) 
        return NSOrderedDescending;
    else if (p1.score>p2.score) 
        return NSOrderedAscending;
    return NSOrderedSame;
}

...
[validPlays sortUsingFunction:SortPlays context:nil];
roocell
la source
5

Vous utilisez NSSortDescriptor pour trier un NSMutableArray avec des objets personnalisés

 NSSortDescriptor *sortingDescriptor;
 sortingDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                       ascending:YES];
 NSArray *sortArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];
Arvind Patel
la source
4
-(NSMutableArray*) sortArray:(NSMutableArray *)toBeSorted 
{
  NSArray *sortedArray;
  sortedArray = [toBeSorted sortedArrayUsingComparator:^NSComparisonResult(id a, id b) 
  {
    return [a compare:b];
 }];
 return [sortedArray mutableCopy];
}
Emile Khattar
la source
pourquoi passer dans un tableau mutable, lorsqu'un nouveau tableau est renvoyé. pourquoi créer un wrapper?
vikingosegundo
3

Le tri NSMutableArrayest très simple:

NSMutableArray *arrayToFilter =
     [[NSMutableArray arrayWithObjects:@"Photoshop",
                                       @"Flex",
                                       @"AIR",
                                       @"Flash",
                                       @"Acrobat", nil] autorelease];

NSMutableArray *productsToRemove = [[NSMutableArray array] autorelease];

for (NSString *products in arrayToFilter) {
    if (fliterText &&
        [products rangeOfString:fliterText
                        options:NSLiteralSearch|NSCaseInsensitiveSearch].length == 0)

        [productsToRemove addObject:products];
}
[arrayToFilter removeObjectsInArray:productsToRemove];
Mohit
la source
2

Trier à l'aide de NSComparator

Si nous voulons trier les objets personnalisés que nous devons fournir NSComparator, qui est utilisé pour comparer les objets personnalisés. Le bloc renvoie une NSComparisonResultvaleur pour indiquer l'ordre des deux objets. Donc, pour trier le tableau entier, il NSComparatorest utilisé de la manière suivante.

NSArray *sortedArray = [employeesArray sortedArrayUsingComparator:^NSComparisonResult(Employee *e1, Employee *e2){
    return [e1.firstname compare:e2.firstname];    
}];

Tri à l'aide de NSSortDescriptor
Supposons, par exemple, que nous avons un tableau contenant des instances d'une classe personnalisée, Employee a des attributs prénom, nom et âge. L'exemple suivant illustre comment créer un NSSortDescriptor qui peut être utilisé pour trier le contenu du tableau dans l'ordre croissant par la clé d'âge.

NSSortDescriptor *ageDescriptor = [[NSSortDescriptor alloc] initWithKey:@"age" ascending:YES];
NSArray *sortDescriptors = @[ageDescriptor];
NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

Tri à l'aide de comparaisons personnalisées Les
noms sont des chaînes et lorsque vous triez des chaînes à présenter à l'utilisateur, vous devez toujours utiliser une comparaison localisée. Souvent, vous souhaitez également effectuer une comparaison insensible à la casse. Voici un exemple avec (localizedStandardCompare :) pour classer le tableau par nom et prénom.

NSSortDescriptor *lastNameDescriptor = [[NSSortDescriptor alloc]
              initWithKey:@"lastName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSSortDescriptor * firstNameDescriptor = [[NSSortDescriptor alloc]
              initWithKey:@"firstName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSArray *sortDescriptors = @[lastNameDescriptor, firstNameDescriptor];
NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

Pour référence et discussion détaillée, veuillez consulter: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/SortDescriptors/Articles/Creating.html
http://www.ios-blog.co.uk/tutorials / objective-c / comment-trier-nsarray-avec-des-objets-personnalisés /

Aamir
la source
1

Les protocoles et la programmation fonctionnelle de Swift rendent cela très simple: il vous suffit de rendre votre classe conforme au protocole comparable, d'implémenter les méthodes requises par le protocole, puis d'utiliser la fonction de tri élevé (par:) pour créer un tableau trié sans avoir besoin d'utiliser tableaux mutables d'ailleurs.

class Person: Comparable {
    var birthDate: NSDate?
    let name: String

    init(name: String) {
        self.name = name
    }

    static func ==(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate === rhs.birthDate || lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedSame
    }

    static func <(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedAscending
    }

    static func >(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedDescending
    }

}

let p1 = Person(name: "Sasha")
p1.birthDate = NSDate() 

let p2 = Person(name: "James")
p2.birthDate = NSDate()//he is older by miliseconds

if p1 == p2 {
    print("they are the same") //they are not
}

let persons = [p1, p2]

//sort the array based on who is older
let sortedPersons = persons.sorted(by: {$0 > $1})

//print sasha which is p1
print(persons.first?.name)
//print James which is the "older"
print(sortedPersons.first?.name)
James Rochabrun
la source
1

Dans mon cas, j'utilise "sortedArrayUsingComparator" pour trier un tableau. Regardez le code ci-dessous.

contactArray = [[NSArray arrayWithArray:[contactSet allObjects]] sortedArrayUsingComparator:^NSComparisonResult(ContactListData *obj1, ContactListData *obj2) {
    NSString *obj1Str = [NSString stringWithFormat:@"%@ %@",obj1.contactName,obj1.contactSurname];
    NSString *obj2Str = [NSString stringWithFormat:@"%@ %@",obj2.contactName,obj2.contactSurname];
    return [obj1Str compare:obj2Str];
}];

Mon objet est aussi,

@interface ContactListData : JsonData
@property(nonatomic,strong) NSString * contactName;
@property(nonatomic,strong) NSString * contactSurname;
@property(nonatomic,strong) NSString * contactPhoneNumber;
@property(nonatomic) BOOL isSelected;
@end
Emre Gürses
la source
1

Vous devez créer sortDescriptor et ensuite vous pouvez trier le nsmutablearray en utilisant sortDescriptor comme ci-dessous.

 let sortDescriptor = NSSortDescriptor(key: "birthDate", ascending: true, selector: #selector(NSString.compare(_:)))
 let array = NSMutableArray(array: self.aryExist.sortedArray(using: [sortDescriptor]))
 print(array)
Parth Barot
la source
1

Utilisez comme ceci pour les objets imbriqués,

NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"lastRoute.to.lastname" ascending:YES selector:@selector(caseInsensitiveCompare:)];
NSMutableArray *sortedPackages = [[NSMutableArray alloc]initWithArray:[packages sortedArrayUsingDescriptors:@[sortDescriptor]]];

lastRoute est un objet et cet objet contient l'objet to, cet objet contient les valeurs de chaîne de nom.

Sureshkumar Linganathan
la source
0

Trier le tableau dans Swift


Pour la Swiftypersonne ci-dessous est une technique très propre pour atteindre l'objectif ci-dessus pour le monde entier. Permet d'avoir un exemple de classe personnalisée Userdont certains ont des attributs.

class User: NSObject {
    var id: String?
    var name: String?
    var email: String?
    var createdDate: Date?
}

Nous avons maintenant un tableau que nous devons trier sur la base de createdDatel'ordre croissant et / ou décroissant. Permet donc d'ajouter une fonction pour la comparaison des dates.

class User: NSObject {
    var id: String?
    var name: String?
    var email: String?
    var createdDate: Date?
    func checkForOrder(_ otherUser: User, _ order: ComparisonResult) -> Bool {
        if let myCreatedDate = self.createdDate, let othersCreatedDate = otherUser.createdDate {
            //This line will compare both date with the order that has been passed.
            return myCreatedDate.compare(othersCreatedDate) == order
        }
        return false
    }
}

Permet maintenant avoir un extensionde Arraypour User. En termes simples, ajoutons quelques méthodes uniquement aux tableaux qui ne contiennent que des Userobjets.

extension Array where Element: User {
    //This method only takes an order type. i.e ComparisonResult.orderedAscending
    func sortUserByDate(_ order: ComparisonResult) -> [User] {
        let sortedArray = self.sorted { (user1, user2) -> Bool in
            return user1.checkForOrder(user2, order)
        }
        return sortedArray
    }
}

Utilisation pour l'ordre croissant

let sortedArray = someArray.sortUserByDate(.orderedAscending)

Utilisation pour l'ordre décroissant

let sortedArray = someArray.sortUserByDate(.orderedAscending)

Utilisation pour la même commande

let sortedArray = someArray.sortUserByDate(.orderedSame)

La méthode ci-dessus extensionne sera accessible que si la Arrayest de type [User]||Array<User>

Syed Qamar Abbas
la source
0

Version Swift: 5.1

Si vous avez une structure ou une classe personnalisée et que vous souhaitez les trier arbitrairement, vous devez appeler sort () à l'aide d'une fermeture de fin qui trie sur un champ que vous spécifiez. Voici un exemple utilisant un tableau de structures personnalisées qui trie sur une propriété particulière:

    struct User {
        var firstName: String
    }

    var users = [
        User(firstName: "Jemima"),
        User(firstName: "Peter"),
        User(firstName: "David"),
        User(firstName: "Kelly"),
        User(firstName: "Isabella")
    ]

    users.sort {
        $0.firstName < $1.firstName
    }

Si vous souhaitez renvoyer un tableau trié plutôt que de le trier sur place, utilisez sorted () comme ceci:

    let sortedUsers = users.sorted {
        $0.firstName < $1.firstName
    }
sDev
la source
0
  let sortedUsers = users.sorted {
    $0.firstName < $1.firstName
 }
manishkumar
la source
La question concerne NSMutableArray, pas la collection Arrays dans Swift
Ricardo
-2
NSMutableArray *stockHoldingCompanies = [NSMutableArray arrayWithObjects:fortune1stock,fortune2stock,fortune3stock,fortune4stock,fortune5stock,fortune6stock , nil];

NSSortDescriptor *sortOrder = [NSSortDescriptor sortDescriptorWithKey:@"companyName" ascending:NO];

[stockHoldingCompanies sortUsingDescriptors:[NSArray arrayWithObject:sortOrder]];

NSEnumerator *enumerator = [stockHoldingCompanies objectEnumerator];

ForeignStockHolding *stockHoldingCompany;

NSLog(@"Fortune 6 companies sorted by Company Name");

    while (stockHoldingCompany = [enumerator nextObject]) {
        NSLog(@"===============================");
        NSLog(@"CompanyName:%@",stockHoldingCompany.companyName);
        NSLog(@"Purchase Share Price:%.2f",stockHoldingCompany.purchaseSharePrice);
        NSLog(@"Current Share Price: %.2f",stockHoldingCompany.currentSharePrice);
        NSLog(@"Number of Shares: %i",stockHoldingCompany.numberOfShares);
        NSLog(@"Cost in Dollars: %.2f",[stockHoldingCompany costInDollars]);
        NSLog(@"Value in Dollars : %.2f",[stockHoldingCompany valueInDollars]);
    }
    NSLog(@"===============================");
Siddhesh Bondre
la source