Efficient Algorithm for comparing and iterate through two large arrays - objective-c

I have this problem:
I want to iterate and compare each item of array1 against each item of array2, both arrays have the same lenght. When the value of both items coincide I store the value j in my indexOfInterest[] array for later use.
This is the code that I use, works well but its extremely slow comparing large arrays (thousands of items), can anyone help me in implement an efficient algorithm for this task.
int i,j;
int counter = [array1 count];
int indexOfInterest[counter];
for (i = 0; i < counter; i++) {
for (j = 0; j < counter; j++) {
if ([[array1 objectAtIndex:i] intValue] == [[array2 objectAtIndex:j]intValue] ) {
indexOfInterest[i] = j;
}
}
}

You can store the indices of array1 in a hashmap (NSDictionary) where the keys are the elements/values and the value is the index of that element (or array of indices if elements are allowed to repeat). Call it map_of_array1.
Then iterate through array2 and find if map_of_array1[array2[[i]] is not null.
This way your time complexity will be O(n+m) instead of O(n*m).

Related

Comparing one array to another

I've got two arrays called Array1 & Array2. Array1 is an array filled with custom objects with multiple properties. Array 2 is an array filled with integers.
I'm trying to compare Array1 to Array2, to see if a int property of an object in Array1 matches an int in Array2.
Currently the code I've got is as follows:
for (int i = 0; i < Array1.count; i++) {
Acorn *acorn = [Array1 objectAtIndex:x];
}
Any advice?
Something like this would help, may be!
for (int i = 0; i < Array1.count; i++) {
Acorn *acorn = [Array1 objectAtIndex:i];
if([Array2 containsObject:acorn.intProp]){
// Take this elements in Array 3 and this will be your filtered array.
}
}

Dividing an array into separate arrays of four elements plus the reminder

I'm trying to divide an array into individual arrays of four elements, where the last array will contain the reminder. For example, if that main array's length property will be ten, three subarrays will be created - two consisting of four elements, and one of two elements.
The code I have right now looks like the following:
NSMutableArray *mainMutableArray = [NSMutableArray arrayWithObjects:#"First", #"Second", #"Third", #"Fourth", #"Fifth", #"Sixth", #"Seventh", #"Eighth", nil];
NSMutableArray *mutableArrayOfSubarrays = [NSMutableArray array];
int length = mainMutableArray.count / 4;
int location = 0;
for (int i = 0; i < length; i++)
{
[mutableArrayOfSubarrays addObject:[mainMutableArray subarrayWithRange:NSMakeRange(location, 4)]];
location += 4;
}
This of course works only when the reminder is equal to 0.
Any help would be greatly appreciated.
Ok, here we go:
int length = mainMutableArray.count;
for (int location = 0; location < length; location+=4)
{
unsigned int Size=length-location;
if (Size>4) Size=4;
[mutableArrayOfSubarrays addObject:[mainMutableArray subarrayWithRange:NSMakeRange(location, Size)]];
}
If you use a while loop, you can make the condition describe what you are actually trying to do:
NSUInteger length = [mainMutableArray count];
NSUInteger location = 0;
// Until the location is less than four away from the end
while( location <= (length - 4) ){
[mutableArrayOfSubarrays addObject:[mainMutableArray subarrayWithRange:NSMakeRange(location, 4)]];
location += 4;
}
// Pick up the remainder, if any
if( location != length ){
[mutableArrayOfSubarrays addObject:[mainMutableArray subarrayWithRange:NSMakeRange(location, length-location)]];
}
Loop from length*4 to mainMutableArray.count to get the remainder of the array.

Shuffling an array of NSNumbers & converting back to ints

I have an NSMutableArray urlArray of size n, I want to randomly choose 4 of these URLs from the total number of elements in the array.
However I don't want to shuffle urlArray directly, I'd prefer to make an "indexArray" [0 ... (n-1)] & shuffle these, & then use the first 4 elements of the shuffled indexArray to decide which elements I choose from urlArray.
First off I created the indexArray as follows:
for (int i = 0; i < numberOfStems; i++) {
[indexArray addObject:[NSNumber numberWithInteger:i]];
}
This allowed me to shuffle my indexArray, so far so good. Because I used the
[NSNumber numberWithInteger:i] method, the elements in the shuffled indexArray are NSNumbers.
Is there a way to convert the NSNumber objects in indexArray into ints?
I attempted to use the intValue function but this didn't appear to be what I needed.
I also tried creating a c style array but that wasn't so successful either - I'd like to stick with objective-c syntax if possible.
Any ideas? any hints appreciated :)
Why don't you just create a normal c array, shuffle that and then use the first four integers in the array as the for random index?
something like
int* index = malloc(numberOfStems*sizeof(int));
for (int i = 0; i < numberOfStems; ++i)
{
index[i] = i;
}
for (int i = numberOfStems - 1; i > 0; --i)
{
int randomIndex = arc4random() % i;
int tmp = index[i];
index[i] = index[randomIndex];
index[randomIndex] = tmp;
}
now use index to access the URL's
EDITED: updated algorithm (although not really related to OP question)
For a temporary array that stores only integers and gets thrown away after a relatively short task I would definitely prefer a C-style array: this would avoid a great deal of overhead, and is also simple to read.
int *array = (int*)malloc(sizeof(int)*numberOfStems);
for (int i = 0 ; i != numberOfStems ; i++) {
array[i] = i;
}
// Do the shuffle
// Pick first four, and do whatever you need to do
// ...
// Now that you are done with the array, do not forget to free it:
free(array);

Array of arrays with ints

How would you go about storing a 2 dimensional array of ints as a class variable?
If you want an array of ints you go:
Class declaration
int * myInts;
Implementation
int ints[3] = {1,2,3};
myInts = ints;
But what if you want to store an array of arrays with ints?
Like this:
int ints[3][3] = {{1,2,3}, {1,2,3}, {1,2,3}};
I don't wanna limit the size of the arrays in the class declaration so I guess I have to go with pointers, but how?
For future reference, this is my conclusion:
Class declaration
int ** ints;
Implementation
int rows = 2;
int cols = 5;
ints = (int**)malloc(rows*sizeof(int*));
ints[0] = (int*)malloc(cols*sizeof(int));
ints[0][0] = 123;
ints[0][1] = 456;
ints[0][2] = 789;
// etc
This is my own interpretation of links provided in comments and my C skills are pretty low so take that into consideration ;) Maybe there are better ways to put in multiple numbers at a time with {123,456,789} or something, but that is beyond my requirements for now!
I've wrote sample for you:
int N = 10, M = 15;
NSMutableArray *ints = [NSMutableArray arrayWithCapacity:N]; // array[N][M]
for (int i=0; i<N; i++)
{
NSMutableArray *arr = [NSMutableArray arrayWithCapacity:M];
for (int j=0; j<M; j++)
{
[arr addObject:[NSNumber numberWithInt:(i+1)*(j+1)]];
}
[ints addObject:arr];
}
// print
for (int i=0; i<[ints count]; i++)
{
NSString *line = #"";
NSMutableArray *arr = [ints objectAtIndex:i];
for (int j=0; j<[arr count]; j++)
line = [NSString stringWithFormat:#"%# %#", line, [arr objectAtIndex:j]];
NSLog(#"%#", line);
}
If you want to dynamically allocate memory, in other words define the size of the arrays at runtime, then you need to declare the array as a pointer, malloc it, and then add another array of ints to each index at runtime. You can't really declare and dynamically allocate at the class level. If you are using cocoa/iphone sdk you can use NSMutableArray.
You could also create your own class that constructs a two dimensional array and exposes methods to push and pop int objects like [IntegerArray push:x,y,n];
Here's and example of using a double reference as Daniel R Hicks pointed out.

Array giving EXC_BAD_ACCESS in for loop

I have a C array defined in my method as:
int c = 4;
int r = 5;
keysArray[c][r];
I have this for loop, which works, populating the keysArray as expected.
for (int row = 0; row < r; row++) {
for (int column = 0; column < c; column++){
keysArray[column][row] = [anotherArray objectAtIndex:0];
NSLog(#"array1 %#",keysArray[column][row]);
[anotherArray removeObjectAtIndex:0];
}
}
Then in a for loop underneath, featuring exactly the same looping counter structure, when i try to NSLog the array, it gives an EXC_BAD_ACCESS.
for (int row = 0; row < r; row++){
for (int column = 0; column < c; column++) {
NSLog(#"array2: %#",keysArray[column][row]); //EXC_BAD_ACCESS here
}
}
What would cause this to happen, given that the keysArray is defined in the method body, outside of both sets of loops?
Are the contents of anotherArray retained by some other object? If not, they do not exist anymore in the second loop. WTH are you using a C array to store Objective-C objects anyway?
int c = 4;
int r = 5;
NSMutableArray *keysArray = [[NSMutableArray alloc] initWithCapacity:c];
for (int column = 0; column < c; column++) {
[keysArray addObject:[NSMutableArray arrayWithCapacity:r]];
for (int row = 0; row < r; row++) {
[[keysArray objectAtIndex:column] addObject:[anotherArray objectAtIndex:0]];
[anotherArray removeObjectAtIndex:0];
}
}
for (int row = 0; row < r; row++){
for (int column = 0; column < c; column++) {
NSLog(#"array2: %#", [[keysArray objectAtIndex:column] objectAtIndex:row]);
}
}
You need to retain the objects held in your C array. Unlikes an NS*Array, a C array does not retain on adding to the array.
However, for a no-holes 2D array like that, I'd just use a single NSMutableArray. Any N-dimensional array can be represented as a line-- as a one dimensional array-- with simple math.
Namely, to determine the index of an object at (X,Y), use (Y * width) + X).
The only caveat is that NS*Array does not support "holes". You will need to fill the array row by row. That is, for a 3x4 (3 wide, 4 tall) array, you would fill it in the order 0,0, 1,0, 2,0, 0,1, 1,1, etc...
Obviously, insert and remove operations will mess up your 2D representation (but they would in an NSMutableArray of NSMutableArrays, too).
Alternatively, use NSPointerArray as it can have holes.
Could this be the problem :
[anotherArray removeObjectAtIndex:0];
try
keysArray[column][row] = [[anotherArray objectAtIndex:0] retain];
although if I were you I would use NSMutableArray of NSMutableArray instead