Shuffle Two NSMutableArray independently - objective-c

I'm creating two NSMutableArray in my viewDidLoad, I add it in a NSMutableDictionary. When I tried shuffling it with one array, It is okay. But the problem is when Im shuffling two arrays independently its not working,somehow the indexes got mixed up.
Here is my code for my array (1st Array):
self.items1 = [NSMutableArray new];
for(int i = 0; i <= 100; i++)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDir stringByAppendingPathComponent:[NSString stringWithFormat:#"[Images%d.png", i]];
if([[NSFileManager defaultManager] fileExistsAtPath:savedImagePath]){
self.container = [[NSMutableDictionary alloc] init];
[container setObject:[UIImage imageWithContentsOfFile:savedImagePath] forKey:#"items1"];
[container setObject:[NSNumber numberWithInt:i] forKey:#"index1"];
[items1 addObject:container];
}
}
NSLog(#"Count : %d", [items1 count]);
[items1 enumerateObjectsUsingBlock:^(id object, NSUInteger index, BOOL *stop) {
NSLog(#"%# images at index %d", object, index);
}];
(2nd Array):
self.items2 = [NSMutableArray new];
for(int i = 0; i <= 100; i++)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDir stringByAppendingPathComponent:[NSString stringWithFormat:#"secondImages%d.png", i]];
NSLog(#"savedImagePath=%#",savedImagePath);
if([[NSFileManager defaultManager] fileExistsAtPath:savedImagePath]){
self.container = [[NSMutableDictionary alloc] init];
[container setObject:[UIImage imageWithContentsOfFile:savedImagePath] forKey:#"items2"];
[container setObject:[NSNumber numberWithInt:i] forKey:#"index2"];
[items2 addObject:container];
}
}
NSLog(#"Count : %d", [items2 count]);
[items2 enumerateObjectsUsingBlock:^(id object, NSUInteger index, BOOL *stop) {
NSLog(#"%# images at index %d", object, index);
}];
My view for the iCarousel where im using my array:
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
if (carousel == carousel1)
{
NSDictionary *obj = [items1 objectAtIndex:index];
view = [[UIImageView alloc] initWithImage:[obj objectForKey:#"items1"]];
view.tag = index;
}
else
{
NSDictionary *obj = [items2 objectAtIndex:index];
view = [[UIImageView alloc] initWithImage:[obj objectForKey:#"items2"]];
view.tag = index;
}
return view;
}
then my shuffle code(Which I tried duplicating for the other array,but not working also):
srandom(time(NULL));
NSUInteger count = [items1 count];
for (NSUInteger i = 0; i < count; ++i) {
int nElements = count - i;
int n = (random() % nElements) + i;
[items1 exchangeObjectAtIndex:i withObjectAtIndex:n];
}
How am I going to shuffle it using above code (or if you have other suggestions) with two arrays? Thanks
My other problem is when I tries subclassing the class for the shuffle method or either use the above code, their index mixed. For example:
Object: apple, ball, carrots, dog
Indexes: 1 2 3 4
but in my View when shuffled:
Object: carrots, apple, dog, balle
Indexes: 2 4 1 3
I also have a method, that when the carousel stop, it will delete the image on view.

the cleanest solution: use a Objective-C Category
NSMutableArray+RandomUtils.h
#import <Foundation/Foundation.h>
#interface NSMutableArray (RandomUtils)
-(void)shuffle;
#end
NSMutableArray+RandomUtils.m
#import "NSMutableArray+RandomUtils.h"
#implementation NSMutableArray (RandomUtils)
-(void)shuffle
{
NSUInteger count = [self count];
for (NSUInteger i = 0; i < count; ++i) {
NSUInteger nElements = count - i;
NSUInteger n = (arc4random() % nElements) + i;
[self exchangeObjectAtIndex:i withObjectAtIndex:n];
}
}
#end
import it, wherever you what to shuffle a MSMutableArray
[array1 shuffle];
[array2 shuffle];
I tried to reproduce your mixed indexes problem, but I can't
NSMutableArray *sarray = [NSMutableArray arrayWithArray: #[#"carrots", #"apple", #"dog", #"balle"]];
NSLog(#"%#", sarray);
[sa enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(#"%# object at index %lu", obj, idx);
}];
[sarray shuffle];
NSLog(#"%#", sarray);
[sarray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(#"%# object at index %lu", obj, idx);
}];
results in
(
carrots,
apple,
dog,
balle
)
carrots object at index 0
apple object at index 1
dog object at index 2
balle object at index 3
(
balle,
dog,
carrots,
apple
)
balle object at index 0
dog object at index 1
carrots object at index 2
apple object at index 3
BTW: your example is aslo incorrect: with four objects in an array the indices should start with 0 and maximum is 3. you have 1 and 4.
so array is shuffled and indexes are ok. You must have some other problem in code, that you didn't show.
You should give up your real code.
I am still ot sure, if I understand, what you want. But from your comments I assume, you want to shuffle an array but keep the old indices. This is just not possible, as the index is the position of an object inside an array. But you are always free to save the original index somewhere.
Or you just copy an array, shuffle one of those. Now ho can ask for the index of an object in both arrays.
NSArray *originalArray = #[#"carrots", #"apple", #"dog", #"balle"];
NSLog(#"%#", originalArray);
[originalArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(#"%# object at index %lu", obj, idx);
}];
NSArray *shuffledArray = [originalArray arrayShuffled];
NSLog(#"%#", shuffledArray);
[shuffledArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(#"%# object at index %lu %lu", obj, idx, [originalArray indexOfObject:obj]);
}];

Assuming the idea is to shuffle two array in the same order then you just need to do the exchange of the 2nd array right after the 1st array?
NSUInteger count = [items1 count];
for (NSUInteger i = 0; i < count; ++i) {
int nElements = count - i;
int n = (random() % nElements) + i;
[items1 exchangeObjectAtIndex:i withObjectAtIndex:n];
[items2 exchangeObjectAtIndex:i withObjectAtIndex:n];
}

Assuming that you have two different array of images which you need to shuffle the images.
for(int i = 0; i <= 100; i++)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDir stringByAppendingPathComponent:[NSString stringWithFormat:#"[Images%d.png", i]];
if([[NSFileManager defaultManager] fileExistsAtPath:savedImagePath]){
//Lazy initialization of dictionary
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:[UIImage imageWithContentsOfFile:savedImagePath] forKey:#"items1"];
[dict setObject:[NSNumber numberWithInt:i] forKey:#"index1"];
[items1 addObject:dict];
[dict release];
}
}
add the object to 2nd array in the same way.
NSUInteger count = [items1 count];
for(int i = 0 ;i < count; i++)
{
int nElements = count - i;
int n = (random() % nElements) + i;
[items1 exchangeObjectAtIndex:i withObjectAtIndex:n];
}
second array shuffling
NSUInteger count = [items2 count];
for(int i = 0 ;i < count; i++)
{
int nElements = count - i;
int n = (random() % nElements) + i;
[items2 exchangeObjectAtIndex:i withObjectAtIndex:n];
}
this should work. If you still find the problem let me know.

Related

combine multiple array values into one string value?

I want to combine the array values into one string.
my arrays are like...
array1=[#"fizan",#"nike",#"pogo"];
array2=[#"round",#"rectangle",#"square"];
array3=[#"frame",#"frame",#"frame"];
I need like this...
value1 = fizan round frame
value2 = nike rectangle frame
value3 = pogo square frame
try this:
NSArray *array1= #[#"fizan",#"nike",#"pogo"];
NSArray *array2= #[#"round",#"rectangle",#"square"];
NSArray *array3= #[#"frame",#"frame",#"frame"];
NSMutableArray *array = [[NSMutableArray alloc] initWithArray:#[array1,array2,array3]];
NSMutableArray *output = [[NSMutableArray alloc] init];
NSString *a;
NSInteger count = array.count;
for (int i = 0; i<array1.count; i++) {
a = #"";
for (int j = 0; j<count; j++) {
a = [a isEqualToString: #""] ? [NSString stringWithFormat:#"%#",[[array objectAtIndex:j] objectAtIndex:i]] : [NSString stringWithFormat:#"%# %#",a,[[array objectAtIndex:j] objectAtIndex:i]];
}
[output addObject:a];
}
for (int i = 0; i < output.count; i++) {
NSLog(#"value %i -> %#",i+1,output[i]);
}
Hope this helps!
UPDATE:
NSArray *array1= #[#"fizan",#"",#"pogo"];
NSArray *array2= #[#"round",#"rectangle",#"square"];
NSArray *array3= #[#"frame",#"frame",#"frame"];
NSMutableArray *array = [[NSMutableArray alloc] initWithArray:#[array1,array2,array3]];
NSMutableArray *output = [[NSMutableArray alloc] init];
NSString *a;
NSInteger count = array.count;
for (int i = 0; i<array1.count; i++) {
a = #"";
for (int j = 0; j<count; j++) {
a = [a isEqualToString: #""] ? [NSString stringWithFormat:#"%#",[[array objectAtIndex:j] objectAtIndex:i]] : [NSString stringWithFormat:#"%# %#",a,[[array objectAtIndex:j] objectAtIndex:i]];
}
[output addObject:a];
}
for (int i = 0; i < output.count; i++) {
NSLog(#"value %i -> %#",i+1,output[i]);
}
I have tested this code. It works perfect. Check again and reconsider the issue.
Do this
NSArray *array1 = #[#"fizan", #"nike", #"pogo"];
NSString *value = [array1 componentsJoinedByString:#" "];
NSLog(#"value = %#", value);
Output will get like
value = fizan nike pogo
For your case
NSArray *completeArray = #[#[#"fizan",#"nike",#"pogo"], #[#"round",#"rectangle",#"square"], #[#"frame",#"frame",#"frame"]];
NSMutableArray *resultArray = [NSMutableArray array];
unsigned long count = 1;
for (int i = 0; i< count; i++) {
NSMutableArray *listArray = [NSMutableArray array];
for (NSArray *itemArray in completeArray) {
count = MAX(count,itemArray.count);
if (i < itemArray.count) {
[listArray addObject:itemArray[i]];
}
}
[resultArray addObject:listArray];
}
for (NSArray *itemArray in resultArray) {
NSString *value = [itemArray componentsJoinedByString:#" "];
NSLog(#"value = %#", value);
}
output
value = fizan round frame
value = nike rectangle frame
value = pogo square frame

Objective-C Split an array into two separate arrays based on even/odd indexes

I have an array, NSMutableArray *stringArray that looks like this
stringArray =
[0]String1
[1]String2
[2]String3
[3]String4
[4]String5
[5]String6
How would I go about splitting this array into two arrays based on even/odd indexes?
Example:
NSMutableArray *oddArray = ([1], [3], [5]);
NSMutableArray *evenArray = ([0], [2], [4]);
Thanks in advance!
create two mutable arrays, use enumerateObjectsWithBlock: on the source array and check idx % 2 to put it into first or second array
Using the ternary operator:
NSArray *array = #[#1,#2,#3,#4,#5,#6,#7,#8,#9,#10,#11,#12];
NSMutableArray *even = [#[] mutableCopy];
NSMutableArray *odd = [#[] mutableCopy];
[array enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
NSMutableArray *evenOrOdd = (idx % 2) ? even : odd;
[evenOrOdd addObject:object];
}];
If you like super compact code you could use the ternary operator like
[((idx % 2) ? even : odd) addObject:object];
If you want to split the array to N arrays, you can do
NSArray *array = #[#1,#2,#3,#4,#5,#6,#7,#8,#9,#10,#11,#12];
NSArray *resultArrays = #[[#[] mutableCopy],
[#[] mutableCopy],
[#[] mutableCopy]];
[array enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
[resultArrays[idx % resultArrays.count] addObject:object];
}];
In Objective-C Categories should come to your mind to create re-uasable code:
#interface NSArray (SplittingInto)
-(NSArray *)arraysBySplittingInto:(NSUInteger)N;
#end
#implementation NSArray (SplittingInto)
-(NSArray *)arraysBySplittingInto:(NSUInteger)N
{
NSAssert(N > 0, #"N cant be less than 1");
NSMutableArray *resultArrays = [#[] mutableCopy];
for (NSUInteger i =0 ; i<N; ++i) {
[resultArrays addObject:[#[] mutableCopy]];
}
[self enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
[resultArrays[idx% resultArrays.count] addObject:object];
}];
return resultArrays;
}
#end
Now you can do
NSArray *array = [#[#1,#2,#3,#4,#5,#6,#7,#8,#9,#10,#11,#12] arraysBySplittingInto:2];
array contains
(
(
1,
3,
5,
7,
9,
11
),
(
2,
4,
6,
8,
10,
12
)
)
Create two NSIndexSets, one for the even indexes and one for the odd, then use objectsAtIndexes: to extract the corresponding slices of the array.
There are following ways you can achieve that:-
The first and second one solution are already mentioned by the above two. Below are the implementation of the same:-
//First Solution
NSArray *ar=#[#"1",#"2",#"3",#"4",#"5"];
NSMutableArray *mut1=[NSMutableArray array];
NSMutableArray *mut2=[NSMutableArray array];
[ar enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
if (idx%2==0)
{
[mut1 addObject:object];
}
else
{
[mut2 addObject:object];
}
}];
//Second Solution
NSMutableIndexSet *idx1 = [NSMutableIndexSet indexSet];
NSMutableIndexSet *idx2 = [NSMutableIndexSet indexSet];
for (NSUInteger index=0; index <ar.count(); index++)
{
if(index%2==0)
{
[idx1 addIndex:index];
}
else{
[idx2 addIndex:index];
}
}
NSArray *evenArr=[ar objectsAtIndexes:idx1];
NSArray *oddArr=[ar objectsAtIndexes:idx2];
NSLog(#"%#",evenArr);
NSLog(#"%#",oddArr);
Got some time for benchmarking and it turns out that when the input array has more than 10 million, it’s faster to use parallel execution.
Here is the concurrent solution that enumerates the input array twice to prevent race conditions on the output arrays.
static NSArray * concurrent(NSArray *input) {
NSUInteger capacity = input.count / 2;
NSArray *split = #[
[NSMutableArray arrayWithCapacity:capacity],
[NSMutableArray arrayWithCapacity:capacity],
];
[split enumerateObjectsWithOptions:NSEnumerationConcurrent
usingBlock:^(NSMutableArray *output, NSUInteger evenOdd, BOOL *stop) {
[input enumerateObjectsUsingBlock:^(id object, NSUInteger index, BOOL *stop) {
if (index % 2 == evenOdd) {
[output addObject:object];
}
}];
}];
return split;
}
I consider this to be the best serial solution, so I used it for benchmarking:
static NSArray * serial(NSArray *input) {
NSUInteger capacity = input.count / 2;
NSMutableArray *even = [NSMutableArray arrayWithCapacity:capacity];
NSMutableArray *odd = [NSMutableArray arrayWithCapacity:capacity];
[input enumerateObjectsUsingBlock:^(id object, NSUInteger index, BOOL *stop) {
NSMutableArray *output = (index % 2) ? odd : even;
[output addObject:object];
}];
return #[ even, odd ];
}
Results
1 million elements
Serial: 54.081 ms
Concurrent: 65.958 ms (18% worse)
10 million elements
Serial: 525.851 ms
Concurrent: 412.691 ms (27% better)
100 million elements
Serial: 5244.798 ms
Concurrent: 4137.939 ms (27% better)
Average of 5 runs.
Input filled with NSNumbers.
Fastest smallest optimization -Os.

Find a dictionary in ArrayOfDictionaries with a specific keyvalue pair

I have an array of dictionaries
for(int i = 0; i < 5; i++) {
NSMutableDictionary *_myDictionary = [NSMutableDictionary dictionary];
[_myDictionary setObject:[NSString stringWithFormat:#"%d",i] forKey:#"id"];
[_myDictionary setObject:label.text #"Name"];
[_myDictionary setObject:label1.text #"Contact"];
[_myDictionary setObject:label2.text #"Gender"];
}
[_myArray addObject:_myDictionary];
Now I want to pick a dictionary from the array whose objectForKey:#"id" is 1 or 2 or something else like there is an sql query Select * from Table where id = 2.
I know this process
int index = [_myArray count];
for(int i = 0; i < 5; i++)
{
NSMutableDictionary *_myDictionary = [NSMutableDictionary dictionaryWithDictionary:[_myArray objectAtIndex:i]];
if([[_myDictionary objectForKey:#"id"] isEqualToString:id])
{
index = i;
return;
}
}
if(index != [_myArray count])
NSLog(#"index found - %i",index);
else
NSLog(#"index not found");
Any help would be appreciated.
Thanks in Advance !!!
Try this, this is by using fast enumeration
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
for(dict in _myArray)
{
if([[dict valueForKey:#"id"] isEqualToString:#"1"])
{
return;
}
}
You should use [NSNumber numberWithInteger: i] not a NSString.
Code fore this search should look like this:
NSString *valueToFind = [NSString stringWithFormat:#"%d", intValue]; // [NSNumber numberWithInteger: intValue]
NSInteger index = [_myArray indexOfObjectPassingTest:^BOOL(NSDictionary *obj, NSUInteger idx, BOOL *stop) {
return [valueToFind isEqualToString: [obj objectForKey: #"id"]];
}];
NSDitionary *found = [_myArray objectAtIndex: index];

replace an object inside nsmutablearray

I have a NSMutableArray where i want to replace the sign | into a ; how can i do that?
NSMutableArray *paths = [dic valueForKey:#"PATH"];
NSLog(#"pathArr ", paths)
pathArr (
(
"29858,39812;29858,39812;29925,39804;29936,39803;29949,39802;29961,39801;30146,39782;30173,39779;30220,39774;30222,39774|30215,39775;30173,39779;30146,39782;29961,39801;29949,39802;29936,39803;29925,39804;29858,39812;29858,39812;29856,39812;29800,39819;29668,39843;29650,39847;29613,39855;29613,39855;29613,39856;29605,39857;29603,39867;29603,39867;29599,39892;29596,39909;29587,39957;29571,40018;29563,40038;29560,40043"
)
)
Update
This is where i got my path from
NSArray *BusRoute = alightDesc;
int i;
int count = [BusRoute count];
for (i = 0; i < count; i++)
{
NSLog (#"BusRoute = %#", [BusRoute objectAtIndex: i]);
NSDictionary *dic = [BusRoute objectAtIndex: i];
NSMutableArray *paths = [dic valueForKey:#"PATH"];
}
Provide that your object in the array path is string, you can do this
NSMutableArray *path2=[[NSMutableArray alloc]initWithArray:nil];
for (NSObject *obect in path) {
for (NSString *string in (NSArray*)obect) {
[path2 addObject:[string stringByReplacingOccurrencesOfString:#"|" withString:#","]];
}
}
NSLog(#"pathArr %# ", path2);
your array paths contains an another array which has string as object.
Hope this helps
//Copy the Array into a String
NSString *str = [paths componentsJoinedByString: #""];
//then replace the "|"
str = [str stringByReplacingOccurrencesOfString:#"|" withString:#";"];
i did this to replace a string in a .plist so it might work for you
array1 = [NSMutableArray arrayWithContentsOfFile:Path1];
NSString *item = [#"dfdfDF"];
[array1 replaceObjectAtIndex:1 withObject:item];
[array1 writeToFile:Path1 atomically:YES];
NSLog(#"count: %#", [array1 objectAtIndex:1]);
you may cast or convert paths to NSString and then do:
paths = (NSString *) [paths stringByReplacingOccurrencesOfString:#"|" withString:#";"];
if this does't work, create new NSString instance that containing pathArr text, invoke replaceOccurrences method and do invert conversion
NSMutableString *tempStr = [[NSMutableString alloc] init];
for (int i = 0; i < [paths count]; i++)
{
[tempStr appendString:[path objectAtIndex:i]];
}
then use this method for tempStr. And then try:
NSArray *newPaths = [tempStr componentsSeparatedByString:#";"];
may be last method not completely correct, so try experiment with it.
Uh, why don't you just go:
NSString *cleanedString = [[[dic valueForKey:#"PATH"] objectAtIndex:0] stringByReplacingOccurrencesOfString:#";" withString:#"|"];
If there are more than one nested array, you can go
for(int i = 0; i < [[dic valueForKey:#"PATH"] count]; i++)
{
NSString *cleanedString = [[[dic valueForKey:#"PATH"] objectAtIndex:i] stringByReplacingOccurrencesOfString:#";" withString:#"|"];
// do something with cleanedString
}

Displaying an array in xcode

I am trying to display the an array with different factors of a number ("prime"). But instead of giving me the int numbers I always get 0,1,2,3,4,5,... .
factors.text = #"";
int factorsNumber;
NSMutableArray *array;
array = [NSMutableArray arrayWithCapacity:5];
for (factorsNumber=1; factorsNumber<=prime; factorsNumber++) {
if (prime%factorsNumber == 0) {
[array addObject:[NSString stringWithFormat:#"%d", factorsNumber]];
}
}
for (int i = 0; i < [array count]; i++) {
[array replaceObjectAtIndex:1 withObject:#"4"];
NSString *temp = [NSString stringWithFormat:#"%d, ", i, [[array objectAtIndex:i] intValue]];
factors.text = [factors.text stringByAppendingString:temp];
}
Replace
NSString *temp = [NSString stringWithFormat:#"%d, ", i, [[array objectAtIndex:i] intValue]];
with
NSString *temp = [NSString stringWithFormat:#"%d, ", [[array objectAtIndex:i] intValue]];
The problem was you were only printing the array index, not the value.