Comment trier un NSArray par ordre alphabétique?

375

Comment trier un tableau rempli [UIFont familyNames]par ordre alphabétique?

DotSlashSlash
la source

Réponses:

725

L'approche la plus simple consiste à fournir un sélecteur de tri ( documentation d' Apple pour plus de détails)

Objectif c

sortedArray = [anArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

Rapide

let descriptor: NSSortDescriptor = NSSortDescriptor(key: "YourKey", ascending: true, selector: "localizedCaseInsensitiveCompare:")
let sortedResults: NSArray = temparray.sortedArrayUsingDescriptors([descriptor])

Apple propose plusieurs sélecteurs pour le tri alphabétique:

  • compare:
  • caseInsensitiveCompare:
  • localizedCompare:
  • localizedCaseInsensitiveCompare:
  • localizedStandardCompare:

Rapide

var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
students.sort()
print(students)
// Prints "["Abena", "Akosua", "Kofi", "Kweku", "Peter"]"

Référence

Thomas Zoechling
la source
5
Le lien de documentation est obsolète, l'exemple de code n'est pas vraiment suffisant pour trier réellement le tableau. localizedCaseInsensitiveCompare: doit être défini d'une manière ou d'une autre.
M. Ryan
34
J'ai mis à jour le lien. Merci d'avoir fait remarquer cela. localizedCaseInsensitiveCompare: est une méthode de NSString et devrait être suffisante pour trier un tableau de chaînes.
Thomas Zoechling
1
Et cela peut être facilement appliqué à un tableau contenant des objets personnalisés (pas seulement NSString). Vous devez simplement vous assurer que tous les objets à l'intérieur de votre tableau ont implémenté le message spécifié par le sélecteur. Ensuite, dans ce message, vous appelez simplement la comparaison NSString pour les propriétés de votre objet que vous souhaitez comparer.
lgdev du
Ces choses simples ne doivent pas être aussi complexes.
Dmitry
276

Les autres réponses fournies ici mentionnent l'utilisation de @selector(localizedCaseInsensitiveCompare:) Cela fonctionne très bien pour un tableau de NSString, cependant si vous voulez étendre cela à un autre type d'objet et trier ces objets en fonction d'une propriété 'name', vous devriez le faire à la place:

NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
sortedArray=[anArray sortedArrayUsingDescriptors:@[sort]];

Vos objets seront triés en fonction de la propriété de nom de ces objets.

Si vous souhaitez que le tri ne respecte pas la casse, vous devez définir le descripteur comme ceci

NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)];
JP Hribovsek
la source
14
+1, merci. C'est drôle, c'est le cas d'utilisation le plus courant que la réponse acceptée.
Vinay W
4
cela trie d'abord les majuscules, puis les minuscules
HarshIT
+1, Le descripteur de tri avec le sélecteur est exactement ce que je voulais et aucune autre réponse ne l'a. Merci beaucoup mec
Ganesh Somani
1
J'obtiens une erreur lorsque j'essaie de trier un tableau de chaînes de cette façon, car ce namen'est pas une clé valide. Quelle clé dois-je utiliser pour trier les chaînes par ordre alphabétique avec un NSSortDescriptor?
temporary_user_name
27

Un moyen plus puissant de trier une liste de NSString pour utiliser des choses comme NSNumericSearch:

NSArray *sortedArrayOfString = [arrayOfString sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
            return [(NSString *)obj1 compare:(NSString *)obj2 options:NSNumericSearch];
        }];

Combiné avec SortDescriptor, cela donnerait quelque chose comme:

NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES comparator:^NSComparisonResult(id obj1, id obj2) {
        return [(NSString *)obj1 compare:(NSString *)obj2 options:NSNumericSearch];
    }];
NSArray *sortedArray = [anArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
Ben G
la source
10

Utilisez le code ci-dessous pour trier par ordre alphabétique:

    NSArray *unsortedStrings = @[@"Verdana", @"MS San Serif", @"Times New Roman",@"Chalkduster",@"Impact"];

    NSArray *sortedStrings =
    [unsortedStrings sortedArrayUsingSelector:@selector(compare:)];

    NSLog(@"Unsorted Array : %@",unsortedStrings);        
    NSLog(@"Sorted Array : %@",sortedStrings);

Voici le journal de la console:

2015-04-02 16:17:50.614 ToDoList[2133:100512] Unsorted Array : (
    Verdana,
    "MS San Serif",
    "Times New Roman",
    Chalkduster,
    Impact
)

2015-04-02 16:17:50.615 ToDoList[2133:100512] Sorted Array : (
    Chalkduster,
    Impact,
    "MS San Serif",
    "Times New Roman",
    Verdana
)
Jayprakash Dubey
la source
10

Une autre méthode simple pour trier un tableau de chaînes consiste à utiliser la descriptionpropriété NSString de cette façon:

NSSortDescriptor *valueDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES];
arrayOfSortedStrings = [arrayOfNotSortedStrings sortedArrayUsingDescriptors:@[valueDescriptor]];
Lisarien
la source
1
Cela semble un peu inutile; il n'y a aucune raison de trier les chaînes de cette façon (et il y a probablement un impact sur les performances pour le faire), et pour d'autres objets, sa propriété de description est rarement utile à des fins de tri.
mah
3

Cela a déjà de bonnes réponses pour la plupart des fins, mais j'ajouterai la mienne qui est plus spécifique.

En anglais, normalement lorsque nous alphabétisons, nous ignorons le mot "the" au début d'une phrase. Ainsi, "Les États-Unis" seraient classés sous "U" et non "T".

Cela fait cela pour vous.

Il serait probablement préférable de les classer en catégories.

// Sort an array of NSStrings alphabetically, ignoring the word "the" at the beginning of a string.

-(NSArray*) sortArrayAlphabeticallyIgnoringThes:(NSArray*) unsortedArray {

    NSArray * sortedArray = [unsortedArray sortedArrayUsingComparator:^NSComparisonResult(NSString* a, NSString* b) {

        //find the strings that will actually be compared for alphabetical ordering
        NSString* firstStringToCompare = [self stringByRemovingPrecedingThe:a];
        NSString* secondStringToCompare = [self stringByRemovingPrecedingThe:b];

        return [firstStringToCompare compare:secondStringToCompare];
    }];
    return sortedArray;
}

// Remove "the"s, also removes preceding white spaces that are left as a result. Assumes no preceding whitespaces to start with. nb: Trailing white spaces will be deleted too.

-(NSString*) stringByRemovingPrecedingThe:(NSString*) originalString {
    NSString* result;
    if ([[originalString substringToIndex:3].lowercaseString isEqualToString:@"the"]) {
        result = [[originalString substringFromIndex:3] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    }
    else {
        result = originalString;
    }
    return result;
}
narco
la source
Je viens de regarder ces années plus tard, et j'ai réalisé qu'il devrait également inclure "un" et "une". Ceux-ci devraient être faciles à ajouter.
narco
1
-(IBAction)SegmentbtnCLK:(id)sender
{ [self sortArryofDictionary];
    [self.objtable reloadData];}
-(void)sortArryofDictionary
{ NSSortDescriptor *sorter;
    switch (sortcontrol.selectedSegmentIndex)
    {case 0:
            sorter=[[NSSortDescriptor alloc]initWithKey:@"Name" ascending:YES];
            break;
        case 1:
            sorter=[[NSSortDescriptor alloc]initWithKey:@"Age" ascending:YES];
            default:
            break; }
    NSArray *sortdiscriptor=[[NSArray alloc]initWithObjects:sorter, nil];
    [arr sortUsingDescriptors:sortdiscriptor];
    }
deepa
la source