How to remove duplicity from array of dictionaries in IOS? [closed] - iphone

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];
}
}
}

Related

Creating a sorted array from a string and an array [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I'm trying to create a sorted array but im having trouble understanding how I would created it.
I have a string (s1) and another array (a1,a2,a3,....).
I want to create a new array using the string and array. I would like to put them in this order (s1 - ar - s1 - ar - s1 -ar).
*ar = the original array in a random order.
How would I go about that creating this array?
Thanks for any help
*Edit: I would like a shuffled array having s1 string at every alternate index
If I understand is correctly you need to create a new array and then one by one fill it up. So like insert the string then take a random element from the array till you run out of elements.
If you want to modify the original array then it has to be mutable (what language are you using?)
in objective-c it would be something like this:
NSString* string;
NSArray* array;
NSMutableArray* temparray = [NSMutableArray arrayWithArray:array];
NSMutableArray* result = [[NSMutableArray alloc] initWithCapacity:[array count]*2];
for (int i=0; i< [array count];i++) {
[result addObject:string];
int index = rand() % [temparray count];
[result addObject:[temparray objectAtIndex:index]];
[temparray removeObjectAtIndex:index];
}
Have a look at NSMutableArray:
NSMutableArray *array = [NSMutableArray arrayWithObjects:#"a1", #"a2", #"a3",nil];
[array insertObject:#"s1" atIndex:0]; // add as first object
[array addObject:#"s2"]; // add as last object
// sort
[array sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
// swap elements
[array exchangeObjectAtIndex:1 withObjectAtIndex:2];
for (NSString *s in array)
{
NSLog(#"elemnt: %#", s);
}
I ended up shuffling the array and adding the string to every even index.
NSMutableArray *array = [NSMutableArray arrayWithObjects:#"a1", #"a2", #"a3", #"a4", #"a5",nil];
[array shuffle];
for (int i = 0 ; i<array.count; i=i+2) {
[array insertObject:#"s1" atIndex:i];
}
NSLog(#"%#",array);
This is how I shuffled the array
NSMutableArray+Shuffling.h
#interface NSMutableArray (Shuffling)
- (void)shuffle;
#end
NSMutableArray+Shuffling.m
#import "NSMutableArray+Shuffling.h"
#implementation NSMutableArray (Shuffling)
- (void)shuffle
{
for (uint i = 0; i < self.count; ++i)
{
// Select a random element between i and end of array to swap with.
int nElements = self.count - i;
int n = arc4random_uniform(nElements) + i;
[self exchangeObjectAtIndex:i withObjectAtIndex:n];
}
}
#end
This I what the output looked like
Array (s1,
a3,
s1,
a5,
s1,
a4,
s1,
a2,
s1,
a1)
Sorry If the question was poorly worded.

Questions app without repetition

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.

Fastest way to compare/set strings

I have an array of Place objects. Each Place object has a name and code property, both strings. Each Place object already has a code, but I need to look up the name property from a server. I get back 2 arrays: one contains name, the other codes. These arrays are ordered so that the name at some index in the nameArray corresponds exactly with the code at the same index of the codeArray.
I have been looping through the array of Place objects, then checking to see if the code property for that Place is the same as the current index in the codeArray. If it is, I set the name of that Place by using the same index in the nameArray:
for(int i = 0; i < [placesArray count]; i++)
{
for(int j = 0; j < [codeArray count]; j++) {
if([[[placesArray objectAtIndex:i] code] isEqualToString:[codeArray objectAtIndex:j]]) {
[[placesArray objectAtIndex:i] setName:[nameArray objectAtIndex:j]];
}
}
}
This works but isn't terribly fast - it can take 30 seconds with 1000+ Places to loop through.
Is there a faster way?
As with anytime you're trying to optimize performance, you should profile the code using Instruments to find out where the bottleneck actually is. That said, looping through the placesArray for each name in the nameArray and doing a string comparison is pretty inefficient.
How about something like this?
NSMutableDictionary *placesByCode = [NSMutableDictionary dictionaryWithCapacity:[placesArray count]];
for (Place *aPlace in placesArray) {
[dictionary setObject:aPlace forKey:aPlace.code];
}
NSMutableDictionary *namesByCode = [NSMutableDictionary dictionaryWithCapacity:[namesArray count]];
for (int i=0; i<[namesArray count]; i++) {
NSString *name = [namesArray objectAtIndex:i];
NSString *code = [codeArray objectAtIndex:i];
[namesByCode setObject:name forKey:code];
}
for (NSString *code in namesByCode) {
Place *place = [placesByCode objectForKey:code];
place.name = [namesByCode objectForKey:namesByCode];
}
Looking up each place by its code in the dictionary should be quite a bit faster than manually looping through the whole place array for each name.
You can use for NSArray -containsObject
if ([myarray containsObject:myObject]) {
// ...
}
Try using a break statement in the inner loop. This way you don't need to loop through the entire loop each time.
for(int i = 0; i < [placesArray count]; i++)
{
for(int j = 0; j < [codeArray count]; j++) {
if([[[placesArray objectAtIndex:i] code] isEqualToString:[codeArray objectAtIndex:j]]) {
[[placesArray objectAtIndex:i] setName:[nameArray objectAtIndex:j]];
break;
}
}
}
You could also make the second array become smaller as you find more results. It will cost you more memory but 1000 strings isn't much anyway.
NSMutableArray * tempCodeArray = [NSMutableArray arrayWithArray:codeArray];
for(int i = 0; i < [placesArray count]; i++)
{
for(int j = 0; j < [tempCodeArray count]; j++) {
if([[[placesArray objectAtIndex:i] code] isEqualToString:[tempCodeArray objectAtIndex:j]]) {
[[placesArray objectAtIndex:i] setName:[nameArray objectAtIndex:j]];
[tempCodeArray removeObjectAtIndex:j];
break;
}
}
}
The problem was not the counting for the array, it's the embedded for loop which will take O(n*n) and in Andrew's solution, it's only O(n)+O(n)+O(n)+whatever take to find a object of the key in the dictionary, which i guess would be in a hash table lookup and that's really fast.
Colby, you probably will be ok with Andrew's solution. If you still wanna improve the performance, then a good idea would be sort the array's first then do lookup.
Hope this helps.

Syntax help - Variable as object name [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
create multiple variables based on an int count
Objective C Equivalent of PHP's “Variable Variables”
How would I create and reference an object using a variable as it's name?
Example -
for (int i=1; i<7; i++) {
CGRect ("myRectNum & i") = myImageView.bounds;
}
("myRectNum & 5").height etc ..
There isn't anything like this in the Objective-C language, and in general it's not going to be a very practical way of referring to data (what if you typo a string? the compiler won't be able to catch it). I won't get into second-guessing what you actually want to do (that would depend on the goal of this part of your application), but you can use an NSMutableDictionary to get a similar effect:
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
for (int i = 0; i < 7; i++)
{
NSString *key = [NSString stringWithFormat:#"myRectNum & %d", i];
NSValue *value = [NSValue valueWithCGRect:myImageView.bounds];
[dict setObject:value forKey:key];
}
Then to fetch the values back out again:
NSValue *value = [dict objectForKey:#"myRectNum & 5"];
CGRect bounds = [value CGRectValue];
NSLog(#"height = %f", bounds.size.height);

iphone Development - pick unique image from array problem, syntax help

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];