Sorting nsarray by index - iphone

I simply want to sort an NSArray by the index number i.e. The order in which the values are entered into the array.
My problem is that I use this array in a uipicker, and therefore when reusing labels, end up with my values in the wrong order
My values consist of fractions. 1/4,3/8,1/2,3/4,1,1-1/14,1-3/8 etc
I want these fractions to display in the order they are entered
Must be simple, but I am having no luck
When I use sorted array localisedstandardcompare all the values get out of sequence
Any help will be appreciated
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
// Only calls the following code if component "0" has changed.
if (component == 0)
{
// Sets the global integer "component0Row" to the currently selected row of component "0"
component0Row = row;
// Loads the new values for the selector into a new array in order to reload the data.
NSDictionary *newDict = [[NSDictionary alloc]initWithDictionary:[pickerData objectForKey:[selectorKeysLetters objectAtIndex:component0Row]]];
NSArray *sortArray = [[NSArray alloc]initWithArray:[newDict allKeys]];
NSMutableArray *newValues = [[NSMutableArray alloc]initWithArray:[sortArray sortedArrayUsingSelector:#selector(compare:)]];
self.selectorKeysNumbers = newValues;
component1Row = 0;
[self.myPicker selectRow:0 inComponent:1 animated:NO];

Your array is already sorted by the index number

Assuming that the array values are NSStrings the sort order will be by string value, not numeric value. In order to sort these fractions (rational numbers) you would have to write you own compare function.
But see #hypercrypt, the array should already be in the order entries were made.

Related

How do I sort an array of custom objects on this property?

I have an array containing custom objects with a property named seat. Seat can have values 1A, 1D , 1C , 1k , 2A, 2k, 2D, 2C.
Now these can be arranged in any order, and I want to sort them according to class, however the sorting only accounts for the seats numeric value and not A, C, D,or K.
I want the order to be 1A,1C,1D,1K and so on.
This is what I have implemented in the SeatDO object:
-(NSComparisonResult) compareBySeatNumber:(SeatDO*)other {
NSComparisonResult result = NSOrderedSame;
NSInteger seatNumber = [self.seat integerValue];
NSInteger otherSeatNumber = [other.seat integerValue];
if (seatNumber > otherSeatNumber) {
result = NSOrderedDescending;
} else if (seatNumber < otherSeatNumber) {
result = NSOrderedAscending;
}
return result;
}
How do I make it consider the letters as well..?
Assuming that you convert the seat numbers to NSStrings
NSArray *sortedSeats = [seats sortedArrayUsingSelector:#selector(localizedStandardCompare:)]
should do the trick. Sorting strings will naturally follow the sort order you need.
Otherwise you could just use strings during the comparison with
[seats sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [[obj1 stringValue] localizedStandardCompare:[obj2 stringValue]];
}];
I assumed that stringValue is available for you custom object. If not, simply replace it with anything that will return a NSString description of your instances.
NOTE
As suggested by Alladinian, you want to use localizedStandardCompare: as opposed to caseInsensitiveCompare:, in order to the get the proper lexicographic order.
Use localizedStandardCompare: as the selector (Finder-like sorting)
[seats sortedArrayUsingSelector:#selector(localizedStandardCompare:)]
While caseInsensitiveCompare: might seem like correct, if you add a #"10D" or #"01C" seat it would appear in front of all others...
if you're using an NSArray you can sort it using sortedArrayUsingSelector:(SEL)comparator and it will return you another array sorted
NSArray *arraySorted = [myArray sortedArrayUsingSelector:#selector(compareBySeatNumber:)];

Sorting array not working properly?

I am sorting a array of string numbers using ios inbuilt sorting method but it is giving me wrong output.So I applied bubble sorting for a while,Any body can explaing why it is behaving like that.So that I can optimize my code.
NSArray *numbers=#[#"45",#"2",#"11",#"31",#"240",#"310"];
numbers=[numbers sortedArrayUsingSelector:#selector(compare:)];
NSLog(#"sorted array is %#",numbers);
NSMutableArray *m_Array=[[NSMutableArray alloc] initWithArray:numbers];
[numbers enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
for (int j=idx+1; j<numbers.count; j++) {
if ([m_Array[idx] intValue]>[m_Array[j] intValue]) {
NSString *temp=m_Array[idx];
[m_Array replaceObjectAtIndex:idx withObject:m_Array[j]];
[m_Array replaceObjectAtIndex:j withObject:temp];
}
}
}];
NSLog(#"sorted array after bubble sort is %#",m_Array);
output is
sorted array is (
11,
2,
240,
31,
310,
45
)
sorted array after bubble sort is (
2,
11,
31,
45,
240,
310
)
That's because you are comparing string objects, not numbers.
Try changing your array to be numbers and not strings (which are in quotes).
In other words, instead of
NSArray *numbers=#[#"45",#"2",#"11",#"31",#"240",#"310"];
you do:
NSArray *numbers=#{#45,#2,#11,#31,#240,#310};
(which are Objective-C literals, as described in this documentation), you'll see much better results.
The reason the "bubble sort" method is working better for you is because you get the "intValue" of your string objects in that array. That's not happening for the first algorithm.
Use NSNumber rather than using string for adding integer values to an array.
NSMutableArray *array =[NSMutableArray alloc]initWithObjects:[NSNumber numberWithInteger:12],[[NSNumber numberWithInteger:122] ];
And then sort
[array sortedArrayUsingSelector:#selector(compare:)]
This is because sorting in Objective-C sorts data with by first element and if the first element is same then it looks for the next one otherwise it sorts on the basis of first element value.suppose case of 11 and 2 , as it checks for first element and first element of 2 is greater than first element of 11 (i.e; 1).So it will declare 2 as greater for sorting purpose.And 2 will come after 11.
For sorting you have to keep prefix values of numbers in order to sort properly.For example: 001,002,003 for 3 digits no and 01,02,03 for two digit no.
NSMutableArray *tempArray=[[NSMutableArray alloc] initWithCapacity:[numbers count]];
[numbers enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[tempArray addObject:[NSString stringWithFormat:#"%03d",[numbers[idx] intValue]]];
}];
NSLog(#"sorted array is %#",[tempArray sortedArrayUsingSelector:#selector(compare:)]);
Note:---Only for variable digit size,--- count maximum no in array and count its digits programmically and set string format accordingly.

Counting PList keys at a specific level

I'm trying to create a grouped tableview, but when it comes to the number rows in sections I haven't been able to get the correct values. From the list below 'OrdreLinje', 'OrdreStatus' and 'KundeLeveranse' are the sections and the items below would be the rows visible to the user. So the number of rows in the sections would be 4,1,1 respectively, my question is how do I count these keys to produce the correct result.
Root(Dict)
-->Rows(Array)
---->Item 0(Dict)
------>OrdreLinje(Array)
-------->item0(Dict)
-------->item1(Dict)
-------->item2(Dict)
-------->item3(Dict)
------>KundeLeveranse(Array)
-------->item0(Dict)
------>OrdreStatus(Array)
-------->item0(Dict)
Sorry, I did try to insert an image but i'm not reputable enough :)
Any help is greatly appreciated,
B
Are you wanting a count of the keys in the first dictionary in the Rows array, or the sum of the keys in all the dictionaries in the Rows array?
For the first, you could do:
NSArray *rows = [rootDict objectForKey:#"Rows"];
NSInteger count = 0;
if (rows.count > 0)
{
NSDictionary *firstRow = [rows objectAtIndex:0];
count = firstRow.allKeys.count;
}
If you want the count of all keys in all dictionaries in the Rows array, you could do:
NSArray *rows = [rootDict objectForKey:#"Rows"];
NSInteger count = 0;
for (NSDictionary *dict in rows)
{
count += dict.allKeys.count;
}

Getting Index of an Object from NSArray?

i am trying to get index of an array through indexOfObject method as follows but when i try to log the value to test the index i get a garbage value.. for testing purposes i am having an array with values {57,56,58..} to get an index of lets say 56,
NSNumber *num = [NSNumber numberWithInteger:56];
NSInteger Aindex = [myArray indexOfObject:num];
NSLog(#" %d",Aindex);
the value i get is something like 2323421. what am i possibly doing wrong??
The index returned by indexOfObject will be the first index for an occurence of your object. Equality is tested using isEqual method.
The garbage value you get is probably equal to NSNotFound.
Try testing anIndex against it. The number you are looking for isn't probably in your array :
NSNumber *num=[NSNumber numberWithInteger:56];
NSInteger anIndex=[myArray indexOfObject:num];
if(NSNotFound == anIndex) {
NSLog(#"not found");
}
or log the content of the array to be sure :
NSLog(#"%#", myArray);
Folks,
When an object is not found in the array the indexOfObject method does NOT return a 'garbage' value. Many systems return an index of -1 if the item is not found.
However, on IOS - because the indexOfObject returns an UNSIGNED int (aka NSUInteger) the returned index must be greater than or equal to zero. Since 'zero' is a valid index there is no way to indicate to the caller that the object was not found -- except by returning an agreed upon constant value that we all can test upon. This constant agreed upon value is called NSNotFound.
The method:
- (NSUInteger)indexOfObject:(id)anObject;
will return NSNotFound if the object was not in the array. NSNotFound is a very large POSITIVE integer (usually 1 minus the maximum int on the platform).
NSNumber *num1 = [NSNumber numberWithInt:56];
NSNumber *num2 = [NSNumber numberWithInt:57];
NSNumber *num3 = [NSNumber numberWithInt:58];
NSMutableArray *myArray = [NSMutableArray arrayWithObjects:num1,num2,num3,nil];
NSNumber *num=[NSNumber numberWithInteger:58];
NSInteger Aindex=[myArray indexOfObject:num];
NSLog(#" %d",Aindex);
Its giving the correct output, may be u have done something wrong with storing objects in ur array.
Try this:
NSArray's indexOfObject: method. Such as the following:
NSUInteger fooIndex = [someArray indexOfObject: someObject];
If you're using Swift and optionals make sure they are unwrapped. You cannot search the index of objects that are optionals.
I just checked. Its working fine for me. Check if your array has the particular number. It will return such garbage values if element is not present.
indexOfObject methord will get the index of the corresponding string in that array if the string is like #"Test" and you find like #"TEST" Now this will retun an index like a long number

Objective-C, How can I produce an array / list of strings and count for each?

My aim is to produce an array, which I can use to add section headers for a UITableView. I think the easiest way to do this, is to produce a sections array.
I want to create section headers for dates, where I'll have several or no rows for each.
So in my populate data array function, I want to populate a display array. So record 1, look for the first date in my display array, create a new array item if it doesn't exist, if it does exist add 1 to the count.
So I should end up with something like this.
arrDisplay(0).description = 1/June/2001; arrDisplay(0).value = 3;
arrDisplay(1).description = 2/June/2001; arrDisplay(1).value = 0;
arrDisplay(2).description = 3/June/2001; arrDisplay(2).value = 1;
arrDisplay(3).description = 5/June/2001; arrDisplay(3).value = 6;
My question is how do I create and use such an array with values, where I can add new elements of add to the count of existing elements and search for existing elements ?
I think, if i understand you, an NSMutableDictionary would work. (as NR4TR said) but, i think the object would be the description and the key would be the count. you could check for the key and get the count in the same gesture. if the return value of objectForKey is nil, it doesn't exist.
NSMutableDictionary *tableDictionary = [[NSMutableDictionary alloc] init];
NSString *displayKey = #"1/June/2001";
NSNumber *displayCount = [tableDictionary objectForKey:displayKey];
if (displayCount != nil) {
NSNumber *incrementedCount = [[NSNumber alloc] initWithInteger:[displayCount integerValue] + 1];
[tableDictionary removeObjectForKey:displayKey];
[tableDictionary setValue:incrementedCount
forKey:displayKey];
[incrementedCount release];
}
else {
NSNumber *initialCount = [[NSNumber alloc] initWithInteger:1];
[tableDictionary setValue:initialCount
forKey:displayKey];
[initialCount release];
}
EDIT: Hopefully this isn't pedantic, but I think a couple pointers will help.
Dictionaries, Sets, and Arrays all hold objects for retrieval. The manner of holding and retrieval desired drives the decision. I think of it based on the question 'what is the nature of the information that I have when I need an object being held?'
NSDictionary and NSMutableDictionary
Hold n objects per key. (I think...I haven't had to test a limit, but i know you can get an NSSet back as a value.)
KEY is more important than INDEX. I don't think of dictionaries as ordered. they know something and you need to ask the correct question.
NSArray and NSMutableArray
hold n objects in order.
INDEX is most important bit of information. (you can ask for the index of an object but, even here, the index is the important part)
you will typically drive table views with an array because the ordered nature of the array fits.
NSSet, NSMutableSet, and NSCountedSet
A collection of objects without order.
You can change any of these into the other with something like [nsset setFromArray:myArray];
and all of these things can hold the other as objects. I think an array as your top level is the correct thinking, but beyond that, it becomes an issue of implementation
Try array of dictionaries. Each dictionary contains two objects - section title and array of section rows.
If you want to have a description AND a rowcount then you can either create a class with those two properties and generate an NSArray of objects with that class or instead of all that you can just use an NSDictionary to store key/value lookups.
I think NSCountedSet is closest to what you want. It doesn't have an intrinsic order, but you can get an array out of it by providing a sort order.