19

I have two arrays. One is an array of names and the other is an array made up of strings titled "Yes" or "No". The index path of each name in the "name" array corresponds with the same index path in the "Yes/No" array. For example:

Names Array | Yes/No Array
Person 1    | Yes
Person 2    | No
Person 3    | Yes

What would be the easiest way to look up a person's name (possibly getting the index path of it) and check whether they are "Yes" or "No" in the "Yes/No" array?

Also, I'm not sure if "index path" is the right term to use. If it isn't, I mean the number that an object is in an array.

PengOne
  • 48,188
  • 17
  • 130
  • 149
Preston
  • 1,039
  • 3
  • 12
  • 22
  • Do you keep the names array sorted or unsorted? –  Jun 18 '11 at 03:18
  • 1
    @Bavarious Unsorted, but it is generated by a server so there are no duplicates. PengOne answered my question though. I was looking for the indexOfObject method. – Preston Jun 18 '11 at 03:21

4 Answers4

31

NSArray has a method called indexOfObject that will return either the lowest index whose corresponding array value is equal to anObject or NSNotFound if no such object is found. If your array of names is unsorted, then use this to get the index that you can then plug in to the Yes/No array. That is, something along these lines:

NSString *answer = nil;
NSUInteger index = [namesArray indexOfObject:@"John Smith"];
if (index != NSNotFound) {
    answer = [yesNoArray objectAtIndex:index];
}
return answer;

Because Bavarious asks questions where I assume, here's a better way when the array of names is sorted alphabetically.

int index = [self findName:@"John Smith"];
NSString *answer = nil;
if (index >= 0) {
    answer = [yesNoArray objectAtIndex:index];
}
return answer;

where the function findName is a simple binary search:

-(int)findName:(NSString *)name {
    int min, mid, max;
    NSComparisonResult comparisonResult;
    min = 0;
    max = [namesArray count]-1;
    while (min <= max) {
        mid = min + (max-min)/2;
        comparisonResult = [name compare:[namesArray objectAtIndex:mid]];
        if (comparisonResult == NSOrderedSame) {
            return mid;
        } else if (comparisonResult == NSOrderedDescending) {
            min = mid+1;
        } else {
            max = mid-1;
        }
    }   
    return -1;  
}
PengOne
  • 48,188
  • 17
  • 130
  • 149
9

Trying to keep two arrays synchronized is just asking for trouble. It can be done, of course, but whenever you modify one array, you have to remember to make a corresponding change to the other. Do yourself a favor and avoid that entire class of bugs by rethinking the way you're storing data.

In this case, you've got a {person, boolean} pair. One option is to store each pair as a dictionary, and then keep an array of those dictionaries. This would be a particularly good plan if you might expand the number of pieces of data beyond the two that you have. Another option would be to just use a dictionary where keys are person names and the values are your yes/no values. This makes the answer to your question very simple:

NSString *yesOrNo = [personDictionary objectForKey:personName];

Getting back to your original question, where you still have the two arrays, the easiest thing to do is to iterate over the person array until you find the person you're looking for, get the index of that name, and then look up the corresponding value in the yes/no array:

for (person in peopleArray) {
    if ([person isEqualToString:thePersonYoureLookingFor]) {
        yesNoValue = [yesNoArray objectAtIndex:[peopleArray indexOfObject:person];
        break;
    }
}

That's fine if the number of people in the list isn't too large. If the list could be large, then you'll want to keep the person array sorted so that you can do a binary search. The trouble there, though, is that you're yes/no array is separate, so sorting the personArray while keeping the yes/no array in the right order becomes complicated.

Caleb
  • 124,013
  • 19
  • 183
  • 272
  • +1: Depending on the requirements, a dictionary/custom class and a sorted array + binary search is a good solution as well. –  Jun 18 '11 at 03:34
  • That is what I originally wanted to do, but I couldn't figure out how to get all of that information from my server. What I am doing right now is requesting the names list and having the server imploding the names, then exploding them into an array in my application. Then doing the same thing for the yes/no array. What would be a better way of doing that? – Preston Jun 18 '11 at 03:38
  • 2
    @Preston, even if you start out with two arrays, it's easy to create a dictionary from two arrays: `peopleDictionary = [NSDictionary dictionaryWithObjects:yesNoArray andKeys:peopleArray];`. It's not much more difficult if you want an array of dictionaries -- just create a loop that constructs a dictionary from corresponding elements of each array and then adds that dictionary to the final array. The custom class that Bavarious alluded to is also a good option, particularly if there's any logic related to a person. – Caleb Jun 18 '11 at 03:43
2

You can also use below of the code, May its useful to you,

NSSortDescriptor *_lastDescriptor = [[NSSortDescriptor alloc] initWithKey:@"" ascending:YES];
NSArray *_lastArray = [NSArray arrayWithObject:_lastDescriptor];


firstCharacterArray = (NSMutableArray *)[[nameIndexesDictionary allKeys]      
sortedArrayUsingDescriptors:_lastArray];
//firstCharacterArray = (NSMutableArray *)[[nameIndexesDictionary allKeys]                    
sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

for (NSString *eachlastIndex in firstCharacterArray)
{
NSSortDescriptor *lastDescriptor = [[NSSortDescriptor alloc] initWithKey:@""
                                                               ascending:YES];
//selector:@selector(localizedCaseInsensitiveCompare:)] ;
NSArray *descriptorslast = [NSArray arrayWithObject:lastDescriptor];
[[nameIndexesDictionary objectForKey:eachlastIndex]     
sortUsingDescriptors:descriptorslast];
[lastDescriptor release];
}
Mayank Jain
  • 5,663
  • 7
  • 32
  • 65
Dinesh_
  • 259
  • 1
  • 5
  • 9
0

You can use indexOfObject method to get the index of element.

for example

This will give you index of your object

  NSInteger index = [yourArray indexOfObject:objectName];

To see the corresponding element from another array

[anotherArray objectAtIndex:index];

This worked for me. Hope this helps.

Pradumna Patil
  • 2,180
  • 3
  • 17
  • 46