I want to make a question app which shows a random question from a plist I made. This is the function (there are only 7 questions for now).
My function gives a random question but it always starts with the same question
and a question can be repeated. I need your help to generate the question randomly and without repetition.
currentQuestion=rand()%7;
NSDictionary *nextQuestion = [self.questions objectAtIndex:currentQuestion];
self.answer = [nextQuestion objectForKey:#"questionAnswer"];
self.qlabel.text = [nextQuestion objectForKey:#"questionTitle"];
self.lanswer1.text = [nextQuestion objectForKey:#"A"];
self.lanswer2.text = [nextQuestion objectForKey:#"B"];
self.lanswer3.text = [nextQuestion objectForKey:#"C"];
self.lanswer4.text = [nextQuestion objectForKey:#"D"];
rand()%7; will always produces a unique sequence of random numbers.
Use arc4random() % 7; instead.
currentQuestion=arc4random() %7;
I'd do it this way (in ARC, written out extra long for clarity):
#property (nonatomic,strong) NSDictionary *unaskedQuestions;
- (NSString *)nextRandomUnaskedQuestion {
if (!self.unaskedQuestions) {
// using your var name 'nextQuestion'. consider renaming it to 'questions'
self.unaskedQuestions = [nextQuestion mutableCopy];
}
if ([self.unaskedQuestions count] == 0) return nil; // we asked everything
NSArray *keys = [self.unaskedQuestions allKeys];
NSInteger randomIndex = arc4random() % [allKeys count];
NSString *randomKey = [keys objectAtIndex:randomIndex];
NSString *nextRandomUnaskedQuestion = [self.unaskedQuestions valueForKey:randomKey];
[self.unaskedQuestions removeObjectForKey:randomKey];
return nextRandomUnaskedQuestion;
}
Use an array of your question keys. Say you have array named arrKeys --> [A], [B], [C], [D], ... , [z], nil
Use (arc4random() % array.length-1) {as suggested by Suresh} to generate rendom index for your array. Say you got rand = 3
Get the key from array arrKeys #3 = D. Then from your NSDictionary use [nextQuestion objectForKey:#"D"] and also remove the 'D' key from your array as [arrKeys removeObjectAtIndex:3]. Repeat 1-3 steps for next question.
Related
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 9 years ago.
Questions must demonstrate a minimal understanding of the problem being solved. Tell us what you've tried to do, why it didn't work, and how it should work. See also: Stack Overflow question checklist
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Improve this question
(
{
color = blue;
},
{
color = blue;
},
{
color = red;
},
{
color = white;
}
)
This is an Array of dictionary, i have to remove duplicate dictionary from array corresponding to key color.
NSSet is to save you in this case. Use:
NSSet *set = [NSSet setWithArray:duplicateArray];
NSArray *uniqueArray = [set allObjects];
Avoid using loop for this because if you have more object loop is a consuming process. You can directly use NSSet and it will work for sure.
Working Code :
NSArray *html = #[#{#"color": #("blue")},#{#"color": #("blue")},#{#"color": #("red")},#{#"color": #("yellow")}];
NSMutableArray *finalArray = [NSMutableArray array];
NSMutableSet *mainSet = [NSMutableSet set];
for (NSDictionary *item in html) {
//Extract the part of the dictionary that you want to be unique:
NSDictionary *dict = [item dictionaryWithValuesForKeys:#[#"color"]];
if ([mainSet containsObject:dict]) {
continue;
}
[mainSet addObject:dict];
[finalArray addObject:item];
}
NSLog(#"%#", finalArray);
An alternative to Vin's solution which I believe would work. But this one does not create a resulting array. It manipulates the existing one. For doing so it creates temporary copies to drive the iterations.
NSArray workingCopy = [NSArray arrayWithArray:yourArray];
for (int i = 0; i < [workingCopy count] - 1; i++) { // count - 1 just saves time. Works nicely without.
for (int j = i+1; j < [workingCopy count]; j++) {
if ([[[workingCopy objectAtIndex:i] objectForKey:#"color"] isEqualToString: [[workingCopy objectAtIndex:j] objectForKey:#"color"]] {
[yourArray removeOjbect:[[workingCopy objectAtIndex:i] objectForKey:#"color"]] // yourArray must be mutable for this.
}
}
}
This algo creates a copy of the original array before. That is to avoid hasseling with changes to the very array that is used for iterations/enumerations. Then it iterates though the copy in a 2-dimensional loop by avoiding to compare the same object with itself (i is never qual to j) and it avoids compaing A with B when B was already compared with A. Both is achieved by stating the j loop with i+1.
The very last iteration would be i = [workingCopy count]. Then j would start off with i+1 and therefore already be larger than [workingCopy count]. The loop's body would not be executed a single time. That's why the i loop can already finish with [workingCopy count] - 1.
The same can be achieved without a copy of the original array. But that does require rather smart manipulations of the running idices i and j, which is no good programming style, rather complex and error prone.
if arr is the array from which you want to remove duplicates
for(int index = 0;index<arr.count;index++){
NSDictionary *dict = [arr objectAtIndex:index];
for(int i = index-1 ; i>=0 ;i++){
NSDictionary *dictToComp = [arr objectAtIndex:i];
if([[dict objectForKey:#"color"] isEqualToString:[dictToComp objectForKey:#"color"]]){
[arr removeObject:dict];
}
}
}
I am having an array of 30 Images i want to add only 15 images to nsmutable dictionary and which are to be added randomly
I am using the following code
for (m = 0; m < 20; m++)
{
rnd = arc4random_uniform(FrontsCards.count);
dic=[[NSMutableDictionary alloc]init];
[dic setObject:[NSNumber numberWithInt:rnd] forKey:#"Images"];
NSLog(#"%#",dic);
}
here the problem is as for m=0 entry gets in dictionary ,for m=1 again an entry goes in dictionary replacing first one and at the end i get only the last value the desired output is all the 20 values can anybody help me out..
Thanks in advance...
You are using the SAME TAG "Images" for every number you set. Hence it gets replaced again and again
dic=[[NSMutableDictionary alloc]init];
for (m = 0; m < 20; m++)
{
rnd = arc4random_uniform(FrontsCards.count);
[dic setObject:[NSNumber numberWithInt:rnd] forKey:[NSString stringWithFormat:#"Images_%d",rnd];
}
NSLog(#"%#",[dic description]);
In this case you need to use NSMutableArray because you are using again and again same key so last value will be replace by new value. So there are 2 option
1) First use different Key for every image.
2) You can use NSMutableArry to add new object.
I found many problem in your code:
1. You want to add 15 images but make loop of 20;
2. You are creating Dictionary in side loop so it will created 20 time. Each time new Dictionary is created and old one get deleted.
3. You ar using same key to store all value. You have to use unique key for each item. Other wise old itel get replaced
Use Like this
dic=[[NSMutableDictionary alloc]init];
for (m = 0; m < 15; m++)
{
rnd = arc4random_uniform(FrontsCards.count);
[dic setObject:[NSNumber numberWithInt:rnd] forKey:[NSString stringWithFormat#"Image%d",rnd]];
}
NSLog(#"%#",dic);
You are allocating new dic evrytime. So it gets overwritten. Try this. Also as mayur said you cant use same key.
dic=[[NSMutableDictionary alloc]init];
for (m = 0; m < 20; m++)
{
rnd = arc4random_uniform(FrontsCards.count);
[dic setObject:[NSNumber numberWithInt:rnd] forKey:[NSString stringWithFormat:#"Images_%d",rnd]];
}
NSLog(#"%#",dic);
You cannot enter more than one object or image with the same key... Here the key is set as Images. So the value for the key named images will be set again and again... Either you have to specify different name for key in each case or use an array to store all images.
Also declare the dictionary outside the for loop. Try the below code.
dic=[[NSMutableDictionary alloc]init];
for (m = 0; m < 20; m++)
{
rnd = arc4random_uniform(FrontsCards.count);
[dic setObject:[NSNumber numberWithInt:rnd] forKey:#"Images_%d", m];
NSLog(#"%#",dic);
}
Above Answer is Right You follow this code and solve your problem.
I have 3 MutableArray's Named:
tvShows
tvNetworks
tvdbID
I need to sort them by the name of the tvShows.
But the need to stay linked.
So e.g.:
tvShows = Breaking Bad, House, Community;
tvNetworks = AMC, FOX, NBC;
tvdbID = 81189, 73255, 94571;
Needs To Become:
tvShows = Breaking Bad, Community, House;
tvNetworks = AMC, NBC, FOX;
tvdbID = 81189, 94571, 73255;
How would I do this? It's my first app so sorry if it's a realy easy question.
store them in an array of dictionaries then sort with an NSArray sort function: (below)
NSDictionary * dict1 = #{#"title":#"breaking bad",#"network":#"AMC",#"tvbdID":#(81189)};
NSDictionary * dict2 = #{#"title":#"house",#"network":#"FOX",#"tvbdID":#(73255)};
NSDictionary * dict3 = #{#"title":#"Community",#"network":#"NBC",#"tvbdID":#(94571)};
NSArray * array = #[dict1,dict2,dict3];
NSSortDescriptor * desc = [NSSortDescriptor sortDescriptorWithKey:#"title"ascending:YES selector:#selector(caseInsensitiveCompare:)];
NSArray * sortedArray = [array sortedArrayUsingDescriptors:#[desc]];
I would personally create a custom NSObject called TVShow, that has properties of showName, network, and tvbdID. This way, you only have one array of each show. Assuming your array is called myShows, you could do something like this:
[allShows sortUsingComparitor:^NSComparisonResult(id a, id b) {
NSString *firstName = [(TVShow*)a showName];
NSString *secondName = [(TVShow*)b showName];
return [firstName compare: secondName];
}];
That is, if you wanted to sort by show name. You can swap network for showName if you wanted to sort by network!
No idea what your end goal is, but you should probably create a TVShow class that has properties (i.e., instance variables) for "title," "network", and "dbid." Then you can instantiate three TVShow objects with their appropriate properties, put them in a mutable array, and use one of the sorting methods on NSMutableArray -- I'd probably choose sortUsingComparator:.
you can't do it with 3 independent arrays but maybe with 1 dictionary where the keys are tv shows and the value is a dictionary with 2 keys: tvNetworks & tvdbIDs
sample:
NSDictionary *data = #{#"Breaking Bad":#{#"tv" : #"AMC", #"tvdb": #(81189)},
#"House":#{#"tv" : #"FOX", #"tvdb": #(73255)},
#"Community":#{#"tv" : #"NBC", #"tvdb": #(94571)}};
NSArray *sortedShows = [data.allKeys sortedArrayUsingSelector:#selector(compare:)];
for (id show in sortedShows) {
NSLog(#"%# = %#", show, data[show]);
}
One of the easiest and most straightforward ways to do this would be to create one array of dictionaries, like this:
NSMutableArray *tvShowInfos = [NSMutableArray array];
for (NSInteger i = 0; i < tvShows.count; i++) {
NSDictionary *info = #{#"show": [tvShows objectAtIndex:i],
#"network": [tvNetworks objectAtIndex:i],
#"id": [tvdbIDs objectAtIndex:i]};
[tvShowInfos addObject:info];
}
You can then sort that array easily:
[tvShowInfos sortUsingDescriptors:#[ [[NSSortDescriptor alloc] initWithKey:#"show" ascending:YES] ]];
If you need an array that contains all networks, sorted by show title, you can then use valueForKey: on the array of dictionaries:
NSArray *networksSortedByShow = [tvShowInfos valueForKey:#"network"];
I am new to iphone programming. I have been struggling with this problem and have tried so many different online solutions but can't get the desired result.
I want to display 2 strings from a random array or dictionary (i'm not sure what is best to use) It would show a random question with the paired answer. Here's what i have so far:
<dict>
<key>q2</key>
<array>
<string>answer2</string>
<string>question2</string>
</array>
<key>q1</key>
<array>
<string>answer1</string>
<string>question1</string>
</array>
.m:
NSString *fileContents = [[NSBundle mainBundle] pathForResource:#"questions" ofType:#"plist"];
NSMutableDictionary *plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:fileContents];
NSMutableArray *array = [plistDict objectForKey:#"q1"];
srandom(time(NULL));
int r = arc4random() %[array count];
NSString *arrayData1 = [array objectAtIndex:r];
NSString *arrayData2 = [array objectAtIndex:r+1];
label1.text = arrayData1;
label2.text = arrayData2;
This shows the correct result. But obviously its only picking it out of the 'q1' array. I would like to be able to get it from any array. Any help would be greatly appreciated. Thanks.
How could this code "show the correct result"? It should crash every second (with the test data you provided) call because of an out of bounds exception caused by this code:
// assume array has 10 objects
int r = arc4random() %[array count]; // r = 9
NSString *arrayData1 = [array objectAtIndex:r]; // index 9, everything ok
NSString *arrayData2 = [array objectAtIndex:r+1]; // index 9 + 1 = 10. exception
If I were you I would radically change the code and the structure of the data. It makes much more sense to use a NSArray for your question and a NSDictionary for each individual question.
If the keys in a dictionary are named q1, q2, q3, q4, and so on there is no reason to use a NSDictionary.
Then you could use something like this, which is much easier to understand and much cleaner.
NSString *pathToQuestions = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"plist"];
NSMutableArray *questions = [[[NSMutableArray alloc] initWithContentsOfFile:pathToQuestions] autorelease];
int questionIndex = arc4random() %[questions count];
NSDictionary *question = [questions objectAtIndex:questionIndex];
NSString *answerStr = [question objectForKey:#"answer"];
NSString *questionStr = [question objectForKey:#"question"];
Since you are using NSMutableArray *array = [plistDict objectForKey:#"q1"]; only the array from q1 will be taken. You have to obtain the array randomly by choosing the key for the dictionary randomly.
UPDATE
For example if u have say 7 arrays of questions named q1,q2,q3,q4,q5,q6,q7. you have to choose an array randomly from this. So you can use
int q = arc4random() %[[plistDict allKeys] count];
NSMutableArray *randomQuestionarray = [[plistDict objectForKey:[NSString stringWithFormat:#"q%d",q]];
This will give you the random array for the questions
#7KV7 is right,you will need randomly formated key's at run time.
For andomly formated key's, you require the starting text of your key, in your case it's q and number of keys,
for example let's suppose you have total 50 key the your key values must be like this
q0,q1,q2, ----- q49.
#include <stdlib.h>
...
...
NSInteger myRandomInt = arc4random() % numberOfKeys ;
NSString myRandomKey = [[NSSting alloc] initWithFormat:#"q%d", myRandomInt];
NSMutableArray *array = [plistDict objectForKey:myRandomKey];
Code:
//pick one filename
int numFileNames = [imageArray count];
int chosen = arc4random() % numFileNames;
NSString *oneFilename = [imageArray objectAtIndex: chosen];
thanks!!
There's one error in your NSMutableArray:
You need to initialize it first.
NSMutableArray *imageArray = [[NSMutableArray alloc] init];
;)
and here's a suggestion, if you do not necessarily require the interface builder's assistance, you might want to consider cocos2d. The stuffs you wanted to do can be done easily in it.
--
as for step 3. Do a random pick using Rand(), make a loop to check if the selected image is already added in an array (this array is for picked images), if it's in the array randomize again, if not then add in into the picked array, and do ball1.image = [UIImage imageNamed:[imageArray objectatindex:randomNum]];
The question does not specify the issue at hand, it just mentions that the developer wants to store a unique image name in array, so coding can be done:
NSMutableArray *arrImages = [NSMutableArray new];
for (int i=0; i<2; i++) {
NSString *imgName = [NSString stringWithFormat:#"imageBall%d",i];
//Here we can check whether image is already added or not.
if (![arrImages contains Object:imgName]) {
[arrImages addObject:imgName];
}
}
int choosen = arc4random() % (int)arrImages.count;
NSString *imageFileName = arrImages[choosen];