I have an NSMutableArray that has NSDictionaries in it. I found a question on SO, and am using this code to sort this NSMutableArray:
NSMutableArray
{
data = {
etc... (for length)
};
number = 1;
},
{
data = {
etc... (for length)
};
number = 3;
},
{
data = {
etc... (for length)
};
number = 4;
},
{
data = {
etc... (for length)
};
number = 2;
}
This array goes up to 80 sub Dictionaries.
NSSortDescriptor
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"number" ascending:YES];
[NSMUTABLEARRAYVAR sortedArrayUsingDescriptors:[NSArray arrayWithObjects:descriptor,nil]];
NSMutableArray *test;
test = [NSMUTABLEARRAYVAR copy];
When I NSLog "test" I get the same order as NSMUTABLEARRAYVAR???
I would appreciate any help in solving this issue, thanks!
sortedArrayUsingDescriptors does not sort the array in place. It returns a newly-sorted array.
sortUsingDescriptors does an in-place sort.
Related
Return an array of NSNumbers with NSIntegers as parameters
I am trying to create an array of NSNumbers between two integers, inclusively.
Two parameters are provided number and otherNumber
Note: either number or otherNumber may be the lower number, but the string always includes numbers from lowest to highest.
I want to be able to return an array of NSNumber between two integers, inclusively.
I am not getting any compiling errors the program runs, however, it's not passing the unit tests. Am I missing something? Your help is greatly appreciated!
- (NSArray *) arrayOfNumbersBetweenNumber:(NSInteger)number andOtherNumber: (NSInteger)otherNumber {
NSNumber *newNumber = [NSNumber numberWithInteger:number];
NSNumber *otherNewNumber = [NSNumber numberWithInteger:otherNumber];
NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:newNumber, otherNewNumber, nil];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:nil ascending:YES];
[mutableArray sortUsingDescriptors:#[sortDescriptor]];
NSArray *myArray = [mutableArray copy];
return myArray;
Objective-C
- (NSArray *)arrayOfNumbersBetweenNumber:(NSInteger)number andOtherNumber:(NSInteger)otherNumber {
NSMutableArray *mutableRange = [NSMutableArray new];
for (NSInteger i = number; i <= otherNumber; i++) {
[mutableRange addObject:#(i)];
}
return [mutableRange copy];
}
You are only adding two numbers, your two bounds, to the array, not all of the intermediary numbers. Also adding numbers and then sorting is pretty inefficient. You can use a simple for loop.
Here is an answer in Swift because a Playground made it easier and I have to leave you some work :)
func arrayOfNumbersBetween(startNumber:NSInteger, endNumber:NSInteger) -> NSArray {
let loopStart=min(startNumber,endNumber)
let loopEnd=max(startNumber, endNumber)
let returnArray=NSMutableArray()
for number in loopStart...loopEnd {
returnArray.addObject(NSNumber(integer: number))
}
return returnArray
}
I have an array that has the past 5 days. It is built like this:
(
"2015-01-27",
"2015-01-26",
"2015-01-25",
"2015-01-24",
"2015-01-23",
)
I have a second NSArray from a FetchRequest
(
{
daySectionIdentifier = "2015-01-24";
sumValue = 2500;
},
{
daySectionIdentifier = "2015-01-25";
sumValue = 1487;
},
{
daySectionIdentifier = "2015-01-27";
sumValue = 750;
}
)
What I want is the dates that match my first array get a value in the first array, the missing dates get no value.
So the final result will look like this:
(
{
daySectionIdentifier = "2015-01-23";
sumValue = 0;
},
{
daySectionIdentifier = "2015-01-24";
sumValue = 2500;
},
{
daySectionIdentifier = "2015-01-25";
sumValue = 1000;
},
{
daySectionIdentifier = "2015-01-26";
sumValue = 0;
},
{
daySectionIdentifier = "2015-01-27";
sumValue = 750;
}
)
Anybody have an idea how to do this? Thanks in advance
Ok so this didn't turn out to be too hard, hopefully this is what you are after:
Firstly thinking about the problem, the issue somewhat here is getting the data in the right format to be able to analyse, so first of all I changed it from an array filled with dictionaries to an array of arrays with each array containing the information (I know not the most elegant solution but one that works none the less)
// Here is our array of past dates
NSArray * pastDateDays = #[#"2015-01-27", #"2015-01-26", #"2015-01-25", #"2015-01-24", #"2015-01-23"];
// Here is our array from the request, this is full of dictionaries
NSArray * fetchRequest = #[#{#"daySectionIdentifier" : #"2015-01-24", #"sumValue": #2500}, #{#"daySectionIdentifier" : #"2015-01-25", #"sumValue": #1487}, #{#"daySectionIdentifier" : #"2015-01-27", #"sumValue": #750}];
// Here is a mutable array we will be adding to
NSMutableArray * request = [NSMutableArray arrayWithArray:fetchRequest];
So now we are ready to start getting the information into a slightly nicer format.
// This function gets the array in an array of arrays where each array has a date and a value
fetchRequest = [self fetchRequestToArray:fetchRequest];
// Not too complicated just taking it out of one and putting it in another
- (NSArray *)fetchRequestToArray: (NSArray *)array {
NSMutableArray * tempArray = [NSMutableArray new];
for (NSDictionary * dict in array) {
NSArray * temp = #[[dict objectForKey:#"daySectionIdentifier"], [dict objectForKey:#"sumValue"]];
[tempArray addObject:temp];
}
return [NSArray arrayWithArray:tempArray];
}
Next we loop through a mutable array of the dates in our date array and if they match in our requested array we remove them:
NSMutableArray * tempDates = [NSMutableArray arrayWithArray:pastDateDays];
for (NSArray * array in fetchRequest) {
NSString * date = array.firstObject;
for (NSString * string in pastDateDays) {
if ([date isEqualToString:string]) {
[tempDates removeObject:string];
}
}
}
This leaves us with an array of dates which are included in our date array but are not included in our requested data. These are the dates we need to add a zero value for.
Again this is relatively simple:
for (NSString * date in tempDates) {
NSDictionary * dict = [NSDictionary dictionaryWithObjects:#[date, #0]
forKeys:#[#"daySectionIdentifier", #"sumValue"]];
[request addObject:dict];
}
This returns us with the desired array.
The only thing that might need to be added is that this array isn't in date order. This can be easily sorted with a number of methods. I found and added this on in a few seconds but you could choose a more complicated one if you need it:
NSSortDescriptor * sortByDate = [NSSortDescriptor sortDescriptorWithKey:#"daySectionIdentifier"
ascending:YES];
NSArray * sortDescriptors = [NSArray arrayWithObject:sortByDate];
NSArray * sortedArray = [request sortedArrayUsingDescriptors:sortDescriptors];
This will output the date in the format:
The final array is the array called request and is a mutableArray
<__NSArrayI 0x7fade848f480>(
{
daySectionIdentifier = "2015-01-23";
sumValue = 0;
},
{
daySectionIdentifier = "2015-01-24";
sumValue = 2500;
},
{
daySectionIdentifier = "2015-01-25";
sumValue = 1487;
},
{
daySectionIdentifier = "2015-01-26";
sumValue = 0;
},
{
daySectionIdentifier = "2015-01-27";
sumValue = 750;
}
)
Which I think is the desired output.
Things to note:
- The values are NSNumbers and not integers as we can't store integers in an NSdictionary
This is not the most elegant solution - I have used a lot of arrays and i am sure it could be refactored. This code though does work and so can be worked with to build understanding - this code should work when copied straight in but there may be a few things needing tweaking as it is a long answer copied from my XCode
The strings need to be in exactly this format for it to work, if they are not then this solution will need to be tweaked.
I hope this helps
My NSArray contains NSDictionary instances, and in the dictionaries I have orderid.
I want to make them sort in descending order. But it is not sorting.
I have tried this code
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"orderid" ascending:FALSE];
[self.orderArray sortUsingDescriptors:[self.orderArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];
And this code :
[self.orderArray sortUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"orderid" ascending:NO]]];
But it didn't worked.
Here is the log
orders : (
{
orderid = 6739;
},
{
orderid = 6740;
},
{
orderid = 6745;
},
{
orderid = 6746;
},
{
orderid = 6748;
},
)
This should work
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"orderid.intValue" ascending:NO ];
[self.orderArray sortUsingDescriptors:#[sortDescriptor]];
I am agree with the #HotLicks this code must work. Are you sure between the sort code and log there is no code. If there is than please add it.
Only problem i see is that You have added your array name instead of NSArray in [self.orderArray sortUsingDescriptors:[self.orderArray arrayWithObject:sortDescriptor]]; this line.
Do it like this :
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"orderid" ascending:FALSE];
[self.orderArray sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]]; //Change in this line
[sortDescriptor release];
NSLog(#"self.orderArray : %#",self.orderArray);
You can sort an array using your "custom" comparator.
NSMutableArray *nds = [[NSMutableArray alloc] initWithArray:nodes];
//
[nds sortUsingComparator:^NSComparisonResult(Node *f1,Node *f2){
if (f1.nodeType == FOLDER && f2.nodeType == FILE) {
return NSOrderedAscending;
} else if (f1.nodeType == FILE && f2.nodeType == FOLDER) {
return NSOrderedDescending;
} else if (f1.nodeType == f2.nodeType) {
return [f1.displayName localizedCaseInsensitiveCompare:f2.displayName];
}
//
return [f1.displayName compare:f2.displayName];
}];
This method will traverse the array, taking two objects from the array and comparing them.
The advantage is that the objects can be of any type (class) and you decide the order between the two.
In the above example I want to order:
- folders before files
- folders and files in alphabetical order
This question already has answers here:
Sorting NSArray of dictionaries by value of a key in the dictionaries
(11 answers)
Closed 9 years ago.
Suppose I would like to sort array by "firstName" key.
Example
Array = (
{
People1 = {
firstName = #"Jack Adam";
email = #"adam#gmail.com";
};
Address = {
cityCode = #"TH";
};
},
People2 = {
firstName = #"Jack DAm";
email = #"dam#gmail.com";
};
Address = {
city = #"TH";
};
);
user Sort Comparator
NSArray *sortedArray = [unsortedArray sortedArrayUsingComparator:^(NSDictionary *a, NSDictionary *b) {
return [a[#"People"][#"firstname"] compare:b[#"People"][#"firstname"]];
}];
But Your Key is inconsistency ...
I Think that data should be
Array = (
{
People = {
firstName = #"Jack Adam";
email = #"adam#gmail.com";
};
Address = {
cityCode = #"TH";
};
},
People = {
firstName = #"Jack DAm";
email = #"dam#gmail.com";
};
Address = {
city = #"TH";
};
);
Using blocks and modern Objective-C syntax:
NSArray *sortedArray = [unsortedArray sortedArrayUsingComparator:^(NSDictionary *first, NSDictionary *second) {
return [first[#"Person"] compare:second[#"Person"]];
}];
Using NSSortDescriptor:
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"firstName" ascending:YES];
myArray=[stories sortedArrayUsingDescriptors:[NSArray arrayWithObjects:descriptor,nil]];
temp = [stories copy]; //temp is NSMutableArray
myArray is the array you want to sort.
First,you should implement a compare-method for your object.
- (NSComparisonResult)compare:(Person *)otherObject {
return [self.birthDate compare:otherObject.birthDate];
}
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingSelector:#selector(compare:)];
As you replied in a comment, the first dictionary key is "Person1" in all array elements.
Then "Person1.firstName" is the key path that gives the first name of each array
element. This key path can be used in a sort descriptor:
NSArray *array = ... // your array
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"Person1.firstName" ascending:YES];
NSArray *sortedArray = [array sortedArrayUsingDescriptors:#[sort]];
the NSMutableArray I want to sort looks like this:
(
{
"title" = "Bags";
"price" = "$200";
},
{
"title" = "Watches";
"price" = "$40";
},
{
"title" = "Earrings";
"price" = "$1000";
}
)
It's an NSMutableArray which contain a collection of NSMutableArrays. I want to sort it by price first then by title.
NSSortDescriptor *sortByPrices = [[NSSortDescriptor alloc] initWithKey:#"price" ascending:YES];
NSSortDescriptor *sortByTitle = [[NSSortDescriptor alloc] initWithKey:#"title" ascending:YES];
[arrayProduct sortedArrayUsingDescriptors:[NSArray arrayWithObjects:sortByPrices,sortByTitle,nil]];
However, that didn't seems to work, how to sort a nested NSMutableArray?
Try
NSMutableArray *arrayProducts = [#[#{#"price":#"$200",#"title":#"Bags"},#{#"price":#"$40",#"title":#"Watches"},#{#"price":#"$1000",#"title":#"Earrings"}] mutableCopy];
NSSortDescriptor *priceDescriptor = [NSSortDescriptor sortDescriptorWithKey:#""
ascending:YES
comparator:^NSComparisonResult(NSDictionary *dict1, NSDictionary *dict2) {
return [dict1[#"price"] compare:dict2[#"price"] options:NSNumericSearch];
}];
NSSortDescriptor *titleDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"title" ascending:YES];
[arrayProducts sortUsingDescriptors:#[priceDescriptor,titleDescriptor]];
NSLog(#"SortedArray : %#",arrayProducts);
I suppose the error is that price is a string. As such, it isn't compared numerically, but lexicographically. Try sorting the array using a comparator block and parsing the price inside that block instead:
[array sortUsingComparator:^(id _a, id _b) {
NSDictionary *a = _a, *b = _b;
// primary key is the price
int priceA = [[a[#"price"] substringFromIndex:1] intValue];
int priceB = [[b[#"price"] substringFromIndex:1] intValue];
if (priceA < priceB)
return NSOrderedAscending;
else if (priceA > priceB)
return NSOrderedDescending;
else // if the prices are the same, sort by name
return [a[#"title"] compare:b[#"title"]];
}];
Try this
Apple doc
This well help you