Create an NSRange with a given minimal and maximal value - objective-c

I have a collection of int64_t values that I need to make an index set out of. I previously have used:
NSIndexSet *set = [NSIndexSet indexSetWithRange:NSMakeRange(location, length)];
to make index sets, but this time its unclear to me how I would do this based on the information I have.
Specifics: I have a collection of values. I know the highest value in the collection, the lowest value in the collection and the number of values in the collection. However, the values are not necessarily consecutive.
For example, if I have the following values: 1,3,4,6,7,9 I would like to create a set that includes all numbers in the collection between and including 1 and 9, i.e. set = 1-9.
How would I do this?
Edit
I shouldn't say I have a "collection" of integers, rather - I have objects stored in core data and each object has an int64_t attribute associated with it, so I don't have a pointer to an actual collection of the objects, and I want to avoid fetching the objects just to create a collection.

Edit: As it turned out in the discussion, the question was how to create a range
with a given minimal and maximal value. This is done with
NSMakeRange(min, max + 1 - min)

Just use a NSMutableIndexSet and add them one by one with the method addIndex

You could do something like this:
NSArray *array = #[#1,#3,#4,#6,#7,#9];
NSMutableIndexSet *set = [[NSMutableIndexSet alloc] init];
for (NSNumber *value in array) {
[set addIndex:[value integerValue]];
}

Related

Unable to sort NSMutableDictionary [Objective C]

I populate an NSMutableDictionary with some Json, the problem is that even if the Json is ordered correctly the NSMutableDictionary reorder the values randomly (at least I don't know what's the logic behind it).
I tried to reorder the NSMutableDictionary using the following method but I still get the same result as the Json:
NSArray* sortedKeys = [theData allKeys];
NSMutableArray* orderHelper = [[NSMutableArray alloc] initWithArray:sortedKeys];
[orderHelper sortUsingComparator:^NSComparisonResult(NSString *str1, NSString *str2) {
return [str1 compare:str2 options:(NSNumericSearch)];
}];
NSMutableDictionary *sortedDictionary = [[NSMutableDictionary alloc] init];
for (NSString *key in orderHelper){
[sortedDictionary setObject:theData[key] forKey:key];
}
where theData is the first NSMutableDictionary containing the Json.
debugging I can see that the NSMutableArray gets ordered correctly but then on the for the NSMutableArray randomly reorders the items.
Does anyone have a solution for this?
Dictionaries (or Maps) are generally not an ordered data structure, and this is also the case for NSDictionary and the like. That means that the iteration order of your dictionary or the order of the allKeys array does not correspond to the insertion order of the associations you put into the dictionary.
So since the order is important to you, you have two options:
1) Use an OrderedDictionary implementation which does exactly that (preserve insertion order). There is none in the Objective-C standard library, but open-source alternatives are available.
2) Keep track of the order yourself in a separate NSArray in which you put the keys of your dictionary. Then, instead of iterating over your dictionary directly, you iterate over this array and read the corresponding values from the dictionary.
The internal order of a dictionary is entirely implementation-specific and of no value to you, since it might even be subject to changes. But very easily put, you can think about it the following way: The dictionary will assign a numerical value to each of your keys (e.g. foo is mapped to 0 and bar to 1. When you insert this key, it will add the value to a bucket at the corresponding numerical index. So regardless of the insertion order, foo will always end up in the first bucket, and bar will always end up in the second bucket. This is the order you can observe when subsequently iterating the dictionary.

Objective-C: How to append uniques items from an array to another array?

I have an array and would like to append N items from another array to it, but only the items not already exist in the current array.
Note, the uniqueness of item is determined not by the object memory but its content. For example, I can have two distinct objects called Person with name "David" and I only one of this in my final result.
What's an efficient way to do this? I have looked at the options of doing it using NSPredicate and NSOrderedSet.
[#[arrayOne,arrayTwo] valueForKeyPath:#"#distinctUnionOfArrays.name"] where name is the property to merge the arrays with.
See NSHipster's KVC Collection Operators
Can be easily achieved using NSSet. Here is an example solution:
//Lines of init can be ignored. Just pay attention to the variables and their comments
NSArray * old = [[NSArray alloc]init]; //Assume this is your old array
NSArray * more = [[NSArray alloc]init]; //Assume this is your extra array
NSArray * new = [[NSArray alloc]init]; //Assume this is your new array (having duplicates)
new = [old arrayByAddingObjectsFromArray:more];
NSArray *cleanedArray = [[NSSet setWithArray:new] allObjects];
For explanation, NSSet automatically removes duplicates.
Warning: It does not preserve the order. If you want to proceed to maintain the order, sort it afterwards, or there are more complex solution on the way.

How to compare an array of numbers and make sure none of the values are the same?

I am randomly generating 6 numbers using
self.number1 = [[NSNumber alloc] initWithInt:((arc4random() %
(hightestNumber-lowestNumber+1)) + lowestNumber)];
I do that for all six numbers, but some of the numbers come out the same. What code can I use to make sure that not any two or more numbers are the same value. I was going to use an if statement to compare the number to all six numbers and then call the arc4random code again but there is a possibility of it coming out the same value of another number again and I would have to test it again after. I really am stumped on this one. Thank you for your help.
What code can I use to make sure that not any two or more numbers are the same value.
A set doesn't have duplicate values, so one option is to add numbers to a set until the size of the set reaches the number of objects you want (6, in your case).
NSMutableSet *set = [NSMutableSet set];
while ([set count] < 6) {
[set addObject:#((arc4random() % (hightestNumber-lowestNumber+1)) + lowestNumber)];
}
Another option is to pick numbers from an existing list, removing each one you choose:
NSArray *list = #[#5, #6, #7, #8, #9, #10, #11, #12, #13];
NSMutableArray *sourceList = [list mutableCopy];
NSMutableArray *finalList = [NSMutableArray array];
for (int i = 0; i < 6; i++) {
// (omitting code to choose a random index for brevity)
[finalList addObject:[sourceList objectAtIndex:randomIndex]];
[sourceList removeObjectAtIndex:randomIndex];
}
This method can work well if the list you're choosing from contains consecutive (or at least monotonically increasing) numbers, since that makes it easy to guarantee that the values in the source list are unique.
In addition to Caleb's excellent suggestions, if the range is relatively small you can create an array with all the values enumerated, shuffle them, and then pick the first 6.

Check if a variable belongs to an enum value

Is there any way to assign a set of values to an enum and check wether a variable has its value in that enum in objective-c.
Something like getting the index of an object in an array if the object is present in an array. I want to give a common behavior, when certain indexes(may not be in order) tapped in my table view, want to avoid if-ing all the indexes, hope I can use enum style.
Objective-C, like most programming languages, doesn't provide a "type membership" test for primitive types - just for object types (e.g. isKindOfClass:) - so using an enum won't solve your problem.
However given that you are thinking of an enum in the first place it sounds like you have a small fixed set of values you wish to check for. In that case you can just use a static array, e.g. something like:
static NSUInteger indices[] = { 2, 42, 57 };
The number of values in such an array is given by sizeof(indices) / sizeof(NSUInteger and you can write a simple loop or binary search to test for membership.
If you wish to use objects then NSSet is a good choice, if the numbers will vary during execution then NSMutableSet. E.g.
NSSet *indices = [NSSet setWithObjects:#2, #42, #57, nil];
and you test for membership using member::
if ([indices member:#indexToTest] != nil) ...
(Note: unlike NSArray the specification for containsObject: for NSSet does not say it uses isEqual:, hence the use of member: here.)
You can't use an enum for that, because you can't enumerate them or call sth. like contains on them. If I understand your correctly I think the straight forward way to do that would be to just use an NSArray to store the indices you care about. Say you want to recognize the indices 2,6 and 14:
NSArray *indices = [NSArray arrayWithObjects: #2, #6, #14, nil];
(The # is necessary because an NSArray can only store objects. The # turns the integers into NSNumber instances.
Then to check if the currently selected index is in it you use:
int indexToCheck = ...;
BOOL indexIsInArray = [index containsObject:#(indexToCheck)];
If your looking for a more 'fancy' (and faster) way to that, you could use bit operations (again using 2,6 and 14 as example):
int indices = 1 << 2 | 1 << 6 | 1 << 14;
and then to check:
int indexToCheck = ...;
BOOL isValid = (1 << indexToCheck) & indices;
where isValid is true when the indexToCheck in one of your indices.
No, internally enums are based on integers, and the mapping happens at compile time. So you need a specific check for every enum type (if they are consecutive numbers, a ">" and "<" check will do).

Sorting delete if 2 numbers are in common [XCODE/OBJ-C]

NSMutableArray *OneNameArray = [NSMutableArray arrayWithArray:ScoreNameArray];
NSMutableArray *OneScoreArray = [NSMutableArray arrayWithArray:RoundOneScoreArray];
NSDictionary *temp = [NSDictionary dictionaryWithObjects:OneNameArray forKeys:OneScoreArray];
NSSortDescriptor *theDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:NO selector:#selector(localizedStandardCompare:)];
RoundOneScoreArray = [[temp allKeys] sortedArrayUsingDescriptors:[NSArray arrayWithObject:theDescriptor]];
ScoreNameArray = [temp objectsForKeys:RoundOneScoreArray notFoundMarker:[NSNull null]];
If theres 2 numbers in common in the score array, then it'll delete one of the numbers.. How can i fix that?
Thanks <3
What I suggest you do is instead of using mutable arrays, use a mutable dictionary. Use a NSNumber as the key, and the name as the object. When you add a new key-value pair, where the key is the same as an older one, the older one will be lost and the newer one kept.
This should greatly reduce your code complexity.
My understanding is that you have an array of names and array of scores. The names are associated to the score by the index of the array (i.e. name[i] has score[i]). In this case one solution will be to implement a sorting algorithm that sorts the array of scores, and takes the array of names along for the ride.
Or perhaps a better plan may be to have the name object have an NSArray member variable that contains that players score for each round. Then you can sort the name array by the score for a given round. Is there any reason this wouldn't work?