Sort NSArray with array of index numbers - ios

I have an array like this:
NSArray *needSortedArray = #[#"Alex", #"Rachel", #"Mohamad"];
and an array of index like this:
NSArray *indexArray = #[#1, #0, #2];
So the output I want will look like this:
needSortedArray = #[#"Rachel", #"Alex", #"Mohamad"];
How can I do this? Is it possible?

Try this:
NSArray *unsortedArray = #[#"Alex", #"Rachel", #"Mohamad"];
NSArray *indexArray = #[#1, #0, #2];
NSMutableArray * sortedArray = [[NSMutableArray alloc] initWithCapacity:unsortedArray.count];
for (NSNumber * num in indexArray)
{
[sortedArray addObject:[unsortedArray objectAtIndex:num.integerValue]];
}
//now sortedArray has sorted objects.

Solution that supports any comparable types of indexes:
NSArray<NSString*> *unsortedArray = #[#"Alex", #"Rachel", #"Mohamad", #"Andrew"];
NSArray<NSNumber*> *indexArray = #[#1, #12, #23, #12];
NSParameterAssert([indexArray count] == [unsortedArray count]);
NSArray* sorted = [unsortedArray sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
NSNumber* index1 = indexArray[[unsortedArray indexOfObjectIdenticalTo:obj1]];
NSNumber* index2 = indexArray[[unsortedArray indexOfObjectIdenticalTo:obj2]];
NSComparisonResult result = [index1 compare:index2];
return result;
}];
NSLog(#"Sorted array: %#", sorted);

Related

sort elements in NSArray based on timestamp of element in my case

I have an array of NSString, each NSString element contains a timestamp (epoch time) and other characters, e.g.: "time:1474437948687, <other characters>".
NSArrary *myData = [self loadData];// my array
So, myData looks like this inside:
{"time:1474437948687,fajlsfj...",
"time:1474237943221, axsasdfd...",
"time:1474681430940, someother...",
...
}
I need to have an array which contains the same elements as the above array, but are sorted in descending order of the timestamp. How can I do it?
I get stuck with iterating over the array of NSString:
for (NSString element in myData) {
...
}
Use following sortedArrayUsingComparator it will work for me : I use static data e.g time:1474437948687, ..
**time:1474437948687, <other characters> Consider String Format..**
NSArrary *myData = [self loadData];
NSArrary *sortedmyData = [[myData sortedArrayUsingComparator: ^(id obj1, id obj2) {
NSDateFormatter *df = [[NSDateFormatter alloc] init];
// Change Date formate accordingly ====
[df setDateFormat:#"dd-MM-yyyy"];
NSDate *d1 = [df dateFromString:[self sperateDate:obj1]];
NSDate *d2 = [df dateFromString:[self sperateDate:obj2]];
return [d1 compare: d2];
}];
// This is function is developed as per time:1474437948687, Consider String Format..
- (NSString *)sperateDate : (NSString *)obj1 {
NSArray *arr = [obj1 componentsSeparatedByString:#","];
NSArray *arr1 = [arr[0] componentsSeparatedByString:#":"];
return arr1[1];
}
Update Compare with primitive type :
NSArray *myData = #[#"time:1474437948687,fajlsfj...",#"time:1474237943221, axsasdfd...",#"time:1474681430940, someother..."
NSArray *sortedmyData = [myData sortedArrayUsingComparator: ^(id obj1, id obj2) {
NSNumber *d1 = [NSNumber numberWithDouble:[[self sperateDate:obj1] doubleValue]];
NSNumber *d2 = [NSNumber numberWithDouble:[[self sperateDate:obj2] doubleValue]];
return [d1 compare: d2];
}];
Hope this help you...
Do let me know if you have any other query
Try this :
NSArray *timearray = #[#"time:1474437948687,fajlsfj...",
#"time:1474237943221, axsasdfd...",
#"time:1474681430940, someother..."];
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#""
ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray = [timearray sortedArrayUsingDescriptors:sortDescriptors];
NSLog(#"sortedArray %#",sortedArray);
Output:
sortedArray (
"time:1474681430940, someother...",
"time:1474437948687,fajlsfj...",
"time:1474237943221, axsasdfd..."
)
First of all it seems to be a good idea to transform the string into instances of an entity type that reflects the data in a key-value manner. Then you can sort it easily by using an instance of NSSortDescriptor:
NSSortDescriptor *timeSorter = [NSSortDescriptor sortDescriptorWithKey:#"time" ascending:NO];
NSArray *sorted = [myData sortedArrayUsingSortDescriptors:#[timeSorter]];
However, you can sort the array as is by using a more complex sort descriptor:
NSSortDescriptor *timeSorter = [NSSortDescriptor sortDescriptorWithKey:#"self" ascending:NO comparator:
^(id one, id two )
{
NSString *timestamp1 = [one compenentsSepartedByString:#","][0];
timestamp1 = [timestamp1 substringFromIndex:5];
NSString *timestamp2 = [two compenentsSepartedByString:#","][0];
timestamp2 = [timestamp2 substringFromIndex:5];
return [timestamp1 compare:timestamp2 options:NSNumericSearch range:NSMakeRange(0, [timestamp1 length])];
}];
NSArray *sorted = [myData sortedArrayUsingSortDescriptors:#[timeSorter]];
Typed in Safari.

iOS - Get unique values from multiple arrays using the same order

I have 2 arrays:
Array one: (#"26", #"26", #"25", #"25", #"3", #"3", #"4", #"4")
Array two: (#"sticker", #"sticker", #"sticker", #"sticker", #"sticker", #"frame", #"frame", #"frame")
Edit
These 2 arrays are connected like this:
26 - sticker
26 - sticker
25 - sticker
25 - sticker
3 - frame
3 - frame
4 - frame
4 - frame
I'm getting unique value in array one and putting it in another array like this:
NSArray *uniqueArrayOne = [[NSSet setWithArray:arrayOne] allObjects];
So uniqueArrayOne looks like this:
(26, 25, 3, 4)
I want uniqueArrayTwo to also be arrange like how uniqueArrayOne was arranged. I want uniqueArrayTwo to look like this:
(sticker, sticker, frame, frame)
What do I do?
Edit
Here is another example:
Array one: (#"TONY", #"SANSA", #"BILL", #"BILL", #"STEVE", #"STEVE")
Array two: (#"STARK", #"STARK", #"GATES", #"GATES", #"JOBS", #"JOBS")
The results should be like this:
uniqueArrayOne :(TONY, SANSA, BILL, STEVE)
uniqueArrayTwo :(STARK, STARK, GATES, JOBS)
uniqueArrayTwo is arrange depending on uniqueArrayOne.
I would solve it this way
- (void)uniqueArrayFinder
{
NSArray *array1 = [[NSArray alloc] initWithObjects:
#"TONY", #"SANSA", #"BILL", #"BILL", #"STEVE", #"STEVE",nil];
NSArray *array2 = [[NSArray alloc] initWithObjects:
#"STARK", #"STARK", #"GATES", #"GATES", #"JOBS", #"JOBS",nil];
NSMutableArray *combinedArray = [[NSMutableArray alloc] init];
for (int i=0; i<[array1 count];i++)
{
NSString *arrayVal1 = [array1 objectAtIndex:i];
NSString *arrayVal2 = [array2 objectAtIndex:i];
NSString *combinedStr = [NSString stringWithFormat:#"%# %#", arrayVal1, arrayVal2];
[combinedArray addObject:combinedStr];
}
//this gives uniqe values
NSSet *uniqueEvents = [NSSet setWithArray:combinedArray];
[combinedArray removeAllObjects];
[combinedArray addObjectsFromArray:[uniqueEvents allObjects]];
NSLog(#"combinedArray: %# ...", combinedArray);
}
Output:
combinedArray: (
"STEVE JOBS",
"TONY STARK",
"SANSA STARK",
"BILL GATES"
) ...
You can achieve the desired result with the following,
NSArray *arr1 = #[#"26", #"26", #"25", #"25", #"3", #"3", #"4", #"4"];
NSArray *arr2 = #[#"sticker", #"sticker", #"sticker", #"sticker", #"sticker", #"frame", #"frame", #"frame"];
NSDictionary *dict = [NSDictionary dictionaryWithObjects:arr2
forKeys:arr1];
NSArray *distinctArr1 = [[NSOrderedSet orderedSetWithArray:arr1] array];
NSMutableArray *distinctArr2 = [NSMutableArray array];
for (NSString *num1 in distinctArr1) {
[distinctArr2 addObject:dict[num1]];
}
// Your distinctArr2 is sorted based on distinctArr1's indices
Try this one.
NSArray *arrayOne = #[#"TONY", #"SANSA", #"BILL", #"BILL", #"STEVE", #"STEVE"];
NSArray *arrayTwo = #[#"STARK", #"STARK", #"GATES", #"GATES", #"JOBS", #"JOBS"];
NSArray *uniqueArrayOne = [[NSSet setWithArray:arrayOne] allObjects];
NSMutableArray *uniqueArrayTwo = [NSMutableArray array];
[uniqueArrayOne enumerateObjectsUsingBlock:^(id _Nonnull obj1, NSUInteger idx, BOOL * _Nonnull stop) {
NSUInteger found = [arrayOne indexOfObjectPassingTest:^BOOL(id _Nonnull obj2, NSUInteger idx, BOOL * _Nonnull stop) {
return [(NSString *)obj2 isEqualToString:(NSString *)obj1];
}];
[uniqueArrayTwo addObject:[arrayTwo objectAtIndex:found]];
}];
NSLog(#"%#, %#", uniqueArrayOne, uniqueArrayTwo);

Sorting an NSArray keeping original indexes rather than values

I have an array of values, and I'd like to sort it from highest to lowest values. Here's my array:
#[#0.985517248005697843460382, #0.000103821940243745174581, #0.002930049254083499140483, #0.006089428685598983863325, #0.000169959081717878927225 #0.038708805305937427077012, #0.005785644142951103588435, #0.003949420720490224266663 #0.003306789895982742942537, #0.005520713777168946394258];
What's the most efficient way to create a new array, but instead of containing the sorted values, it would contain the indexes from the original array?
Currently this is what I'm doing:
NSArray *array = #[#3, #5, #7, #2, #4, #4.1, #1, #10];
NSArray *sortedArray = [array sortedArrayUsingSelector: #selector(compare:)];
NSMutableArray *arraySortedByOriginalIndexes = [[NSMutableArray alloc] init];
for (int i = 0; i < sortedArray.count; i++) {
NSUInteger index = [array indexOfObject:sortedArray[i]];
[arraySortedByOriginalIndexes addObject:#(index)];
}
Here is the simple solution if no numbers in array are equal.
NSArray *sortedArray = [array sortedArrayUsingSelector: #selector(compare:)];
NSMutableArray *mutableIndexes = [NSMutableArray array];
for (NSNumber *number in sortedArray) {
[mutableIndexes addObject:#([array indexOfObject:number])];
}
NSArray *indexes = [mutableIndexes copy];
Again, it only works when no numbers are equal.

How to sort a NSArray with another NSArray?

NSArray A = #[[[#"id":#"3"]], [[#"id":#"4"]] ,[[#"id":#"c"]],[[#"id":#"f"]]];
NSArray idArray = #[#"c", #"3", #"4",#"f"];
Just a example I assumed.
How can I sort A by its id with idArray?
That is, I want A to become:
NSArray A= #[[[#"id":#"c"]], [[#"id":#"3"]] ,[[#"id":#"4"]],[[#"id":#"f"]]];
Now, I want to ask for an algorithm to sort array A to get the desired result.
---I get my answer when I search in google:
NSArray *sorter = #[#"B", #"C", #"E"];
NSMutableArray *sortee = [#[
#[#"B", #"abc"],
#[#"E", #"pqr"],
#[#"C", #"xyz"]
] mutableCopy];
[sortee sortUsingComparator:^(id o1, id o2) {
NSString *s1 = [o1 objectAtIndex:0];
NSString *s2 = [o2 objectAtIndex:0];
NSInteger idx1 = [sorter indexOfObject:s1];
NSInteger idx2 = [sorter indexOfObject:s2];
return idx1 - idx2;
}];
If you want to compare both array you can use
NSArray *array1=#[#"3",#"4",#"c","f"];
NSArray *array2=#[#"c",#"3",#"4","f"];
array1=[array1 sortedArrayUsingSelector:#selector(compare:)];
array2=[array2 sortedArrayUsingSelector:#selector(compare:)];
if ([array1 isEqualToArray:array2]) {
NSLog(#"both are same");
}
else{
NSLog(#"both are differnt");
}
or If you want to get common elements from 2 array use
NSMutableSet* set1 = [NSMutableSet setWithArray:array1];
NSMutableSet* set2 = [NSMutableSet setWithArray:array2];
[set1 intersectSet:set2]; //this will give you only the obejcts that are in both sets
NSArray* result = [set1 allObjects];
This would be a better way to make a dictionary for A. And then sorting based on their specific values like IQ, Name etc.
NSArray A = #[[[#"id":#"3"]], [[#"id":#"4"]] ,[[#"id":#"c"]],[[#"id":#"f"]]];
NSArray idArray = #[#"c", #"3", #"4",#"f"];
NSMutableArray *array = [NSMutableArray array];
for (int id = 0;idx<[A count];id++) {
NSDictionary *dict = #{#"Name": A[id],#"IQ":idArray[id]};
[array addObject:dict];
}
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:#"IQ" ascending:NO];
[array sortUsingDescriptors:#[descriptor]]

Sort an NSMutableDictionary

I have an NSMutableDictionary that maps NSString to NSString (although the values are NSStrings, they are really just integers).
For example consider the following mappings,
"dog" --> "4"
"cat" --> "3"
"turtle" --> "6"
I'd like to end up with the top 10 entries in the dictionary sorted by decreasing order of the value. Can someone show me code for this? Perhaps there is an array of keys and another array of values. However it is, I don't mind. I'm just trying to have it be efficient.
Thank you!
Get the Array of the Values, sort that array and then get the key corresponding to the value.
You can get the values with:
NSArray* values = [myDict allValues];
NSArray* sortedValues = [values sortedArrayUsingSelector:#selector(comparator)];
But, if the collection is as you show in your example, (I mean, you can infer the value from the key), you can always sort the keys instead messing with the values.
Using:
NSArray* sortedKeys = [myDict keysSortedByValueUsingSelector:#selector(comparator)];
The comparator is a message selector which is sent to the object you want to order.
If you want to order strings, then you should use a NSString comparator.
The NSString comparators are i.e.: caseInsensitiveCompare or localizedCaseInsensitiveCompare:.
If none of these are valid for you, you can call your own comparator function
[values sortedArrayUsingFunction:comparatorFunction context:nil]
Being comparatorFunction (from AppleDocumentation)
NSInteger intSort(id num1, id num2, void *context)
{
int v1 = [num1 intValue];
int v2 = [num2 intValue];
if (v1 < v2)
return NSOrderedAscending;
else if (v1 > v2)
return NSOrderedDescending;
else
return NSOrderedSame;
}
The simplest way is:
NSArray *sortedValues = [[yourDictionary allValues] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSMutableDictionary *orderedDictionary=[[NSMutableDictionary alloc]init];
for(NSString *valor in sortedValues){
for(NSString *clave in [yourDictionary allKeys]){
if ([valor isEqualToString:[yourDictionary valueForKey:clave]]) {
[orderedDictionary setValue:valor forKey:clave];
}
}
}
Use this method:
- (NSArray *)sortKeysByIntValue:(NSDictionary *)dictionary {
NSArray *sortedKeys = [dictionary keysSortedByValueUsingComparator:^NSComparisonResult(id obj1, id obj2) {
int v1 = [obj1 intValue];
int v2 = [obj2 intValue];
if (v1 < v2)
return NSOrderedAscending;
else if (v1 > v2)
return NSOrderedDescending;
else
return NSOrderedSame;
}];
return sortedKeys;
}
Call it and then create a new dictionary with keys sorted by value:
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:
#"4", #"dog",
#"3", #"cat",
#"6", #"turtle",
nil];
NSArray *sortedKeys = [self sortKeysByIntValue:dictionary];
NSMutableDictionary *sortedDictionary = [[NSMutableDictionary alloc] init];
for (NSString *key in sortedKeys){
[sortedDictionary setObject:dictionary[key] forKey:key];
}
Sorting the keys and using that to populate an array with the values:
NSArray *keys = [dict allKeys];
NSArray *sKeys = [keys sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
NSMutableArray *sValues = [[[NSMutableArray alloc] init] autorelease];
for(id k in sKeys) {
id val = [dict objectForKey:k];
[sValues addObject:val];
}
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"interest" ascending:YES];
[unsortedArray sortUsingDescriptors:[NSArray arrayWithObjects:descriptor,nil]];
recentSortedArray = [stories copy];
if you want to sort data in ascending order for key 'name' for such kind of Example then this may help you.
arrayAnimalList = [
{
'name' = Dog,
'animal_id' = 001
},
{
'name' = Rat,
'animal_id' = 002
},
{
'name' = Cat,
'animal_id' = 003
}
];
This is a code which help you to get sorted array
//here you have to pass key for which you want to sort data
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:descriptor];
// here you will get sorted array in 'sortedArray'
NSMutableArray * sortedArray = [[arrayAnimalList sortedArrayUsingDescriptors:sortDescriptors] mutableCopy];

Resources