I'm new to Objective-C and I'm trying to create a simple dictionary style app for personal use. Right now I'm attempting to make a loop that prints randomly selected NSArrays that have been added to an NSDictionary. I'd like to print each array only once. Here is the code I'm working with:
NSArray *catList = [NSArray arrayWithObjects:#"Lion", #"Snow Leopard", #"Cheetah", nil];
NSArray *dogList = [NSArray arrayWithObjects:#"Dachshund", #"Pitt Bull", #"Pug", nil];
...
NSMutableDictionary *wordDictionary = [[NSMutableDictionary alloc] init];
[wordDictionary setObject: catList forKey:#"Cats"];
[wordDictionary setObject: dogList forKey:#"Dogs"];
...
NSInteger keyCount = [[wordDictionary allKeys] count];
NSInteger randomKeyIndex = arc4random() % keyCount;
int i = keyCount;
for (i=i; i>0; i--) {
NSString *randomKey = [[wordDictionary allKeys] objectAtIndex:randomKeyIndex];
NSMutableArray *randomlySelectedArray = [wordDictionary objectForKey:randomKey];
NSLog(#"%#", randomlySelectedArray);
}
This code prints the same array "i" times. Any pointers on how to exclude previously printed arrays from being printed again?
I'm wondering if removeObjectForKey: could be of any use.
You just need to re-calculate the random key index every time you go through the loop, and then, as you suggest, use removeObjectForKey:.
Something like this:
NSArray *catList = [NSArray arrayWithObjects:#"Lion", #"Snow Leopard", #"Cheetah", nil];
NSArray *dogList = [NSArray arrayWithObjects:#"Dachshund", #"Pitt Bull", #"Pug", nil];
//...
NSMutableDictionary *wordDictionary = [[NSMutableDictionary alloc] init];
[wordDictionary setObject: catList forKey:#"Cats"];
[wordDictionary setObject: dogList forKey:#"Dogs"];
//...
while ([wordDictionary count] > 0) {
NSInteger keyCount = [wordDictionary count];
NSInteger randomKeyIndex = arc4random() % keyCount;
NSString *randomKey = [[wordDictionary allKeys] objectAtIndex:randomKeyIndex];
NSMutableArray *randomlySelectedArray = [wordDictionary objectForKey:randomKey];
NSLog(#"%#", randomlySelectedArray);
[wordDictionary removeObjectForKey: randomKey];
}
In your code, you generate a random randomKeyIndex, then use it without changing its value i times in the loop. So you get i times the same array.
NSInteger randomKeyIndex = arc4random() % keyCount;
// ...
for (i=i; i>0; i--) {
NSString *randomKey = [[wordDictionary allKeys] objectAtIndex:randomKeyIndex];
// ...
}
As you say removeObjectForKey is an option for you, you can change your code into something like this:
NSInteger keyCount = [[wordDictionary allKeys] count];
for (i=keyCount; i>0; i--) {
NSInteger randomKeyIndex = arc4random() % keyCount;
NSString *randomKey = [[wordDictionary allKeys] objectAtIndex:randomKeyIndex];
NSMutableArray *randomlySelectedArray = [wordDictionary objectForKey:randomKey];
[wordDictionary removeObjectForKey:randomKey];
keyCount--;
NSLog(#"%#", randomlySelectedArray);
}
Related
I have a twodimensional array where i i would like to print all second values of the objects into an UIlabel homePlayersFouls. the problem is i do not know how to this.
I have tried following things:
componentsJoinedByString:#"\n".
This will just print (
The other thing ive tried is this:
[[homePlayersArray objectAtIndex:i] objectAtIndex:1];
this just prints 0 since it looping and deleting the content inside label
i've checked wether there is something wrong the the array, but when i do this inside the loop:
nslog(#"%#",[[homePlayersArray objectAtIndex:i] objectAtIndex:1];);
It prints all 0 0 0 which is the 3 second values in my objects.
The question is then how can i print all my second values in all the objects in the array into an UIlabel?
here is the complete code:
for (int i=0;i<[homeNumbersArray count];i++){
NSArray *tempArray = [[NSArray alloc] initWithObjects:[homeNumbersArray objectAtIndex:i],[NSNumber numberWithInt:0], nil];
[homePlayersArray addObject:tempArray];
NSObject* someObject = [[homePlayersArray objectAtIndex:i] objectAtIndex:1];
homePlayersFouls.text = [NSString stringWithFormat:#"%#", someObject];
}
You need:
homePlayersFouls.text = [homePlayersFouls.text stringByAppendingString:[NSString stringWithFormat:#"%#", someObject]];
NSMutableString *fouls = [NSMutableString string];
for (int i=0;i<[homeNumbersArray count];i++){
NSArray *tempArray = [[NSArray alloc] initWithObjects:[homeNumbersArray objectAtIndex:i],[NSNumber numberWithInt:0], nil];
[homePlayersArray addObject:tempArray];
NSObject* someObject = [[homePlayersArray objectAtIndex:i] objectAtIndex:1];
[fouls appendFormat:#"%#", someObject];
}
homePlayersFouls.text = fouls;
I have one NSArray with names in string objects like this:#[#"john", #"smith", #"alex",
#"louis"], and I have another array that contains lots of names. How can I check that all the objects in the first array are in the second?
NSSet has the functionality that you are looking for.
If we disregard performance issues for a moment, then the following snippet will do what you need in a single line of code:
BOOL isSubset = [[NSSet setWithArray: array1] isSubsetOfSet: [NSSet setWithArray: mainArray]];
Use this code..
NSArray *temp1 = [NSArray arrayWithObjects:#"john",#"smith",#"alex",#"loui,#"Jac", nil];
NSArray *temp2 = [NSArray arrayWithObjects:#"john",#"smith",#"alex",#"loui,#"Rob", nil];
NSMutableSet *telephoneSet = [[NSMutableSet alloc] initWithArray:temp1] ;
NSMutableSet *telephoneSet2 = [[NSMutableSet alloc] initWithArray:temp2];
[telephoneSet intersectSet:telephoneSet2];
NSArray *outPut = [telephoneSet allObjects];
NSLog(#"%#",outPut);
output array contains:
"john","smith","alex","loui
as per your requirement.
Run a loop and use isEqualToStiring to verify whether array1 objects exists in mainArray.
int num_of_matches = 0;
for(NSString *name in mainArray)
{
if(array1 containsObject:name){
num_of_matches++;
}
}
if(num_of_matches == [array1 count]{
// All objects present
}else {
// Matched number is equal of number_of_matches
}
If you just need to check if all objects from array1 are in mainArray, you should just use NSSet
e.g.
BOOL isSubset = [[NSSet setWithArray:array1] isSubsetOfSet:[NSSet setWithArray:mainArray]]
if you need to check which objects are in mainArray, you should take a look at NSMutableSet
NSMutableSet *array1Set = [NSMutableSet setWithArray:array1];
[array1Set intersectSet:[NSSet setWithArray:mainArray]];
//Now array1Set contains only objects which are present in mainArray too
Use NSArray filteredArrayUsingPredicate: method. Its really fast to find out similar types of object in both arrays
NSPredicate *intersectPredicate = [NSPredicate predicateWithFormat:#"SELF IN %#", otherArray];
NSArray *intersectArray = [firstArray filteredArrayUsingPredicate:intersectPredicate];
From above code intersect array gives you same objects which are in other array.
Try this way;
NSArray *mainArray=#[#"A",#"B",#"C",#"D"];
NSArray *myArray=#[#"C",#"x"];
BOOL result=YES;
for(id object in myArray){
if (![mainArray containsObject:object]) {
result=NO;
break;
}
}
NSLog(#"%d",result); //1 means contains, 0 means not contains
You can use the concept of [NSArray containsObject:], where your objects will be from your array1 like you say "john","smith","alex","loui"
NSArray *array1 = [NSArray arrayWithObjects:#"a", #"u", #"b", #"v", #"c", #"f", nil];
NSMutableArray *mainArray = [NSMutableArray arrayWithObjects:#"a", #"u", #"I", #"G", #"O", #"W",#"Z",#"C",#"T", nil];
int j=0;
for(int i=0; i < mainArray.count; i++)
{
if (j < array1.count)
{
for( j=0; j <= i; j++)
{
if([[mainArray objectAtIndex:i] isEqualToString:[array1 objectAtIndex:j]] )
{
NSLog(#"%#",[mainArray objectAtIndex:i]);
}
}
}
}
I need to extract a NSDictionary from a NSMutableArray, and extract an object from that dictionary.
The code should be quite easy, but I keep having a SIGABRT error on the NSDictionary declaration.
-(void)calcolaConto {
conto = [[NSNumber alloc] initWithDouble:0];
for (int i=0; [shoppingListItems count]; ++i) {
NSDictionary *dictVar = (NSDictionary *) [shoppingListItems objectAtIndex:i]; //<-- SIGABRT
NSNumber *IO = (NSNumber *) [dictVar objectForKey:#"incout"];
NSNumber *priceValue = (NSNumber *) [dictVar objectForKey:#"price"];
if ([IO isEqualToNumber:[NSNumber numberWithInt:0]]) {
conto = [NSNumber numberWithDouble:([conto doubleValue] + [priceValue doubleValue])];
} else if ([IO isEqualToNumber:[NSNumber numberWithInt:1]]) {
conto = [NSNumber numberWithDouble:([conto doubleValue] - [priceValue doubleValue])];
}
NSLog(#"Valore %#", conto);
}
}
"shoppingListItems" is created in this way:
NSMutableDictionary *rowDict = [[NSMutableDictionary alloc] initWithCapacity:6];
[rowDict setObject:primaryKeyValue forKey: ID];
[rowDict setObject:itemValue forKey: ITEM];
[rowDict setObject:priceValue forKey: PRICE];
[rowDict setObject:groupValue forKey: GROUP_ID];
[rowDict setObject:incOut forKey:INC_OUT];
[rowDict setObject:dateValue forKey: DATE_ADDED];
[shoppingListItems addObject: rowDict];
The problem is that your loop never stops. You should use:
for (NSUInteger i = 0; i < [shoppingListItems count]; i++) {
or:
for (NSDictionary* dictVar in shoppingListItems) {
so that you do not try to access an element that is out of bounds. In your
current loop i will be incremented until it reaches [shoppingListItems count]
which is beyond the end of the array, so objectAtIndex will throw an exception.
I have an Array {-1,0,1,2,3,4...}
I am trying to find whether an element exist in these number or not, code is not working
NSInteger ind = [favArray indexOfObject:[NSNumber numberWithInt:3]];
in ind i am always getting 2147483647
I am filling my array like this
//Loading favArray from favs.plist
NSString* favPlistPath = [[NSBundle mainBundle] pathForResource:#"favs" ofType:#"plist"];
NSMutableDictionary* favPlistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:favPlistPath];
NSString *favString = [favPlistDict objectForKey:#"list"];
NSArray *favList = [favString componentsSeparatedByString:#","];
//int n = [[favList objectAtIndex:0] intValue];
favArray = [[NSMutableArray alloc] initWithCapacity:100];
if([favList count]>1)
{
for(int i=1; i<[favList count]; i++)
{
NSNumber *f = [favList objectAtIndex:i];
[favArray insertObject:f atIndex:(i-1)];
}
}
That's the value of NSNotFound, which means that favArray contains no object that isEqual: to [NSNumber numberWithInt:3]. Check your array.
After second edit:
Your favList array is filled with NSString objects. You should convert the string objects to NSNumber objects before inserting them in favArray:
NSNumber *f = [NSNumber numberWithInt:[[favList objectAtIndex:i] intValue]];
The goal is to generate an NSString chars in length and assign each string to an array. I'm getting stuck on what I need to do with my algorithm to get the correct result. Here's the sample. The result I get is the same randomly generated string added to my array 26 times instead of 26 DIFFERENT strings added.
I've thought about declaring 26 different NSStrings and assigning each result from the algorithm to each string, but that seems inefficient. Thanks for the help.
NSMutableString *string = #"expert";
NSUInteger strLength = [string length];
NSString *letterToAdd;
NSString *finishedWord;
NSMutableString *randomString = [NSMutableString stringWithCapacity: strLength];
NSMutableArray *randomArray = [[NSMutableArray alloc] init];
NSArray *charArray = [[NSArray alloc] initWithObjects: #"a", #"b", #"c", #"d",
#"e", #"f", #"g", #"h", #"i", #"j", #"k", #"l", #"m",
#"o", #"p", #"q", #"r", #"s", #"t", #"u", #"v", #"w",
#"x", #"y", #"z", nil];
for (int a = 0; a < 26; a++) {
for (int i = 0; i < strLength; i++) {
letterToAdd = [charArray objectAtIndex: arc4random() % [charArray count]];
if([randomString length] < strLength) {
[randomString insertString: letterToAdd atIndex: i];
}
finishedWord = randomString;
}
[randomArray addObject: finishedWord];
}
NSLog(#"Random Array count %i, contents: %#", [randomArray count], randomArray);
Here's how I would do it:
#import "NSString+Shuffle.h"
NSString * string = #"expert";
NSUInteger strLength = [string length];
NSString * alphabet = #"abcdefghijklmnopqrstuvwxyz";
NSMutableSet * randomWords = [NSMutableSet set];
while ([randomWords count] < 26) {
NSString * newWord = [alphabet shuffledString];
newWord = [newWord substringToIndex:strLength];
[randomArray addObject:newWord];
}
NSLog(#"Random set count %d, contents: %#", [randomWords count], randomWords);
You'd then need a category on NSString that defines shuffledString. This method would simply take the characters in the string and rearrange them randomly. Decent shuffle algorithms can be found quite easily with Google.
I hope you get the basic idea of how this works. The only modification I made is using an NSSet instead of an NSArray, and what the conditional on the loop is. The eliminates the (slim) possibility of duplicate random words.
Edit: since I'm feeling generous, here's a basic shuffledString implementation:
//NSString+Shuffle.h
#interface NSString (ShuffleAdditions)
- (NSString *) shuffledString;
#end
//NSString+Shuffle.m
#import "NSString+Shuffle.h"
#implementation NSString (ShuffleAdditions)
- (NSString *) shuffledString {
NSMutableString * shuffled = [self mutableCopy];
NSUInteger length = [shuffled length];
for (int i = 0; i < (4*length); ++i) {
NSString * randomChar = [shuffled subStringWithRange:NSMakeRange(arc4random() % (length-1), 1)];
[shuffled appendString:randomChar];
}
return [shuffled autorelease];
}
#end
You should create a new randomString each time:
NSMutableString *string = #"expert";
NSUInteger strLength = [string length];
NSString *letterToAdd;
NSString *finishedWord;
//NSMutableString *randomString = [NSMutableString stringWithCapacity: strLength];
NSMutableArray *randomArray = [[NSMutableArray alloc] init];
NSArray *charArray = [[NSArray alloc] initWithObjects: #"a", #"b", #"c", #"d", #"e", #"f",
#"g", #"h", #"i", #"j", #"k", #"l", #"m", #"o", #"p", #"q", #"r", #"s",
#"t", #"u", #"v", #"w", #"x", #"y", #"z", nil];
for (int a = 0; a < 26; a++) {
NSMutableString *randomString = [NSMutableString stringWithCapacity: strLength];
for (int i = 0; i < strLength; i++) {
letterToAdd = [charArray objectAtIndex: arc4random() % [charArray count]];
//if([randomString length] < strLength) {
[randomString insertString: letterToAdd atIndex: i];
//}
//finishedWord = randomString;
}
//[randomArray addObject: finishedWord];
[randomArray addObject: randomString];
}
NSLog(#"Random Array count %i, contents: %#", [randomArray count], randomArray);
You're adding the same object to your array every time through the loop, and overwriting it as you go. You mentioned:
I've thought about declaring 26 different NSStrings and assigning each
result from the algorithm to each string...
And that is indeed exactly what you need to do. Moving the initialization of randomString into the loop will solve your problem (getting a new NSMutableString on every loop iteration, rather than using a single object). Change the definition of randomString to a simple type definition:
NSMutableString *randomString;
and then in your outer loop, add this line:
randomString = [NSMutableString stringWithCapacity:strLength];
You shouldn't need to change any of the rest of your code.