67

I have an array populated by dictionaries, and I need to sort the array alphabetically by the values of one of the keys of the dictionaries.

This is my array:

tu dictus: (
    {
    brand = Ryul;
    productTitle = Any;
    quantity = 1;
    subBrand = "Ryul INJ";
    type = Product;
},
    {
    brand = Trol;
    productTitle = Different;
    quantity = 2;
    subBrand = "";
    type = Brand;
},
    {
    brand = Dtor;
    productTitle = Any;
    quantity = 1;
    subBrand = "";
    type = Product;
},
    {
    brand = Ryul;
    productTitle = Different;
    quantity = 2;
    subBrand = "Ryul CHES";
    type = SubBrand;
},
    {
    brand = Anan;
    productTitle = Any;
    quantity = 1;
    subBrand = "";
    type = Product;
}
)

Normally for sorting an array I will use

myArray = [uniqueProdsArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

But how do sort using the brand key of the dictionary?

jscs
  • 63,694
  • 13
  • 151
  • 195
manuelBetancurt
  • 15,428
  • 33
  • 118
  • 216
  • 1
    This kind of sorting is also called a `Schwartzian Transform`. I have made a swift package for this: https://github.com/neoneye/SwiftySchwartzianTransform – neoneye Jun 24 '18 at 21:38

11 Answers11

113

I think this will do it:

brandDescriptor = [[NSSortDescriptor alloc] initWithKey:@"brand" ascending:YES];
sortDescriptors = [NSArray arrayWithObject:brandDescriptor];
sortedArray = [myArray sortedArrayUsingDescriptors:sortDescriptors];

I pulled the code from Sort Descriptor Programming Topics. Also, Key-Value Coding comes into play, in that sortedArrayUsingDescriptors: will send a valueForKey: to each element in myArray, and then use standard comparators to sort the returned values.

Cœur
  • 37,241
  • 25
  • 195
  • 267
QED
  • 9,803
  • 7
  • 50
  • 87
9

We Got The Solution By Using The Method Follows

[self.jsonData sortUsingDescriptors: [NSArray arrayWithObjects: [NSSortDescriptor sortDescriptorWithKey:"fullname" ascending:YES], [NSSortDescriptor sortDescriptorWithKey:"id" ascending:NO], nil]];

Where:-

jsonData - MutableArray Which holds the Parsed JSON Data.

fullname - the data we want to sort.

id - An unique data which comes with the inner dictionary.

Prabhu Natarajan
  • 869
  • 1
  • 9
  • 13
5

As an addition to QED's code,

NSSortDescriptor * brandDescriptor = [[NSSortDescriptor alloc] initWithKey:@"brand" ascending:YES];
NSArray * sortedArray = [myArray sortedArrayUsingDescriptors:@[brandDescriptor]];

This clarifies the classes of the variables and optimises the array creation with fast-enumeration. Thanks

mylogon
  • 2,772
  • 2
  • 28
  • 42
4
 arrSorted = [arrBrand sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
            if ([[obj1 valueForKey:@"iUserId"] integerValue] > [[obj2 valueForKey:@"iUserId"] integerValue]) {
                return (NSComparisonResult)NSOrderedDescending;
            }
            if ([[obj1 valueForKey:@"iUserId"] integerValue] < [[obj2 valueForKey:@"iUserId"] integerValue]) {
                return (NSComparisonResult)NSOrderedAscending;
            }
            return (NSComparisonResult)NSOrderedSame;
        }];
SteveFerg
  • 3,466
  • 7
  • 19
  • 31
Hardip Kalola
  • 196
  • 1
  • 4
  • While sortedArrayUsingComparator is the way to go, having up to four calls to "valueForKey" instead of two calls to "objectForKey" is bad. BTW. Since you expect dictionaries, use NSDictionary* as the type, not id. – gnasher729 Nov 19 '15 at 09:58
4

In switf:

var descriptor: NSSortDescriptor = NSSortDescriptor(key: "brand", ascending: true)
var sortedResults: NSArray = results.sortedArrayUsingDescriptors([descriptor])
HDmast
  • 316
  • 5
  • 15
4

Use following code for sort using the "brand" key from the dictionary..

NSSortDescriptor * brandDescriptor = [[NSSortDescriptor alloc] initWithKey:@"brand" ascending:YES];
NSArray * sortDescriptors = [NSArray arrayWithObject:brandDescriptor];
NSArray * sortedArray = [myArray sortedArrayUsingDescriptors:sortDescriptors];
NSLog(@"sortedArray %@",sortedArray);

Use following code, If you to sorting according two keys from the dictionary; Like, "brand" key and productTitle key from the dictionary:-

NSSortDescriptor * brandDescriptor = [[NSSortDescriptor alloc] initWithKey:@"brand" ascending:YES];
NSSortDescriptor * productTitleDescriptor = [[NSSortDescriptor alloc] initWithKey:@"productTitle" ascending:YES];
NSArray * sortDescriptors = [NSArray arrayWithObjects:brandDescriptor, productTitleDescriptor, nil];
NSArray * sortedArray = [feedData sortedArrayUsingDescriptors:sortDescriptors];
NSLog(@"sortedArray %@",sortedArray);
Meet Doshi
  • 4,241
  • 10
  • 40
  • 81
2

My code was crashing when using NSSortDescriptor so ended up using a block which works great in my use case, where I am expecting the "rank" to be an NSNumber. If the object can't be converted to an integer it will not sort but it also won't cause a crash.

NSArray *sortedArray = [data sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    long data1 = [[obj1 valueForKey:@"rank"] integerValue];
    long data2 = [[obj2 valueForKey:@"rank"] integerValue];
    if (data1 > data2) {
        return (NSComparisonResult)NSOrderedDescending;
    }
    if (data1 < data2) {
        return (NSComparisonResult)NSOrderedAscending;
    }
    return (NSComparisonResult)NSOrderedSame;
}];
OffensivelyBad
  • 621
  • 8
  • 16
1

Just try it out easiest way...

myArray = [[NSMutableArray alloc] init];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
[tempArray removeAllObjects];
[tempArray addObjectsFromArray: myArray];

NSString *key = @"brand";
NSSortDescriptor *brandDescriptor = [[NSSortDescriptor alloc] initWithKey:key ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:brandDescriptor,nil];
NSArray *sortedArray = [tempArray sortedArrayUsingDescriptors:sortDescriptors];
[brandDescriptor release];
[tempArray removeAllObjects];
tempArray = (NSMutableArray*)sortedArray;
[myArray removeAllObjects];
[myArray addObjectsFromArray:tempArray];
P.J.Radadiya
  • 1,493
  • 1
  • 12
  • 21
IOS Rocks
  • 2,127
  • 2
  • 21
  • 24
1

you can do this .

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"d LLLL yyyy"];

NSComparator compareDates = ^(id string1, id string2)
{
    NSDate *date1 = [formatter dateFromString:string1];
    NSDate *date2 = [formatter dateFromString:string2];

    return [date1 compare:date2];
};
NSSortDescriptor * sortDesc1 = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO comparator:compareDates];
[array sortUsingDescriptors:[NSArray arrayWithObjects:sortDesc1, nil]];
P.J.Radadiya
  • 1,493
  • 1
  • 12
  • 21
Sishu
  • 1,510
  • 1
  • 21
  • 48
1
NSSortDescriptor *brandDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"Position" ascending:YES selector:@selector(localizedStandardCompare:)] autorelease];
      NSArray *sortDescriptors = [NSArray arrayWithObject:brandDescriptor];
      NSArray  *sortedArray = [arrTemp sortedArrayUsingDescriptors:sortDescriptors];
     array_PreLagData=(NSMutableArray*)sortedArray;

unsorted array
Printing description of arrTemp:
<__NSArrayM 0x10282100>(
{
    Milker2 = "11:03:17 AM";
    Position = 2;
},
{
    Milker1 = "11:03:28 AM";
    Position = 25;
},
{
    Milker3 = "11:03:18 AM";
    Position = 3;
},
{
    Milker1 = "11:03:16 AM";
    Position = 1;
    Strip = "11:32:32 AM";
},
{
    Milker1 = "11:03:21 AM";
    Position = 10;
}
)
Sorted array
<__NSArrayI 0x101363c0>(
{
    Milker1 = "11:03:16 AM";
    Position = 1;
    Strip = "11:32:32 AM";
},
{
    Milker2 = "11:03:17 AM";
    Position = 2;
},
{
    Milker3 = "11:03:18 AM";
    Position = 3;
},
{
    Milker1 = "11:03:21 AM";
    Position = 10;
},
{
    Milker1 = "11:03:28 AM";
    Position = 25;
}
)

[enter link description here][1]


  [1]: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/SortDescriptors/Articles/Creating.html#//apple_ref/doc/uid/20001845-BAJEAIEE
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
jbchitaliya
  • 211
  • 2
  • 13
0

Use this for swift 4

let sortedArray = arrayTobeSort.sorted {$0["keyName"].compare($1["keyName"]) == ComparisonResult.orderedAscending}

You can also use ComparisonResult.orderedDescending to sort in descending order

Avneesh Agrawal
  • 916
  • 6
  • 11