I have an NSArray which contains a few duplicate objects. I want to print which objects are getting duplicated, for example:
NSArray * array = [NSArray arrayWithObjects: A, B, C, A, B];
Now I want to print in my console A & B as these are duplicated.
How do I do this?
You can use NSCountedSet for this. you can add all the objects in a counted set, then use the countForObject: method to find out how often each object appears. read about NSCountedSet for further reference
Use an NSCountedSet and only print the elements that returns a number>1 for countForObject: method
It's probably far from perfect, but it works
NSArray *array = [NSArray arrayWithObjects:#"a", #"b", #"b", #"v", #"f", #"f", nil];
NSMutableArray *un_array = [NSMutableArray array];
NSMutableArray *dupArray = [NSMutableArray array];
for (id obj in array)
{
if (![un_array containsObject:obj])
[un_array addObject:obj];
else
[dupArray addObject:obj];
}
NSLog(#"DUPLICATES:");
for (id obj in dupArray)
NSLog(#"%#", [obj description]);
Another approach is to sort the array and look for adjacent duplicates. Probably a little slower than using a hashed set approach, but the same basic "big O".
Related
I have an array [1,2,3,4]
I need to continously shift and push one element into the same array
so that the first variable values will be 1,2,3,4,1,2,3,4,...
and second variable values will be 2,3,4,1,2,3,4,1,...
How to do that??
Use NSMutableArray like:
1) to get the object at the first position:
object = [nameArray firstObject];
[nameArray removeObjectAtIndex:0];
2) then insert it in last position:
[nameArray addObject:object];
p.s. remember to always add some sanity checks.
You would need
- exchangeObjectAtIndex:withObjectAtIndex:
Exchanges the objects in the array at given indices.
See Documentation here
Example
NSMutableArray *array = [NSMutableArray array];
[array setArray:#[#"Eezy",#"Tutorials",#"Website"]];
[array exchangeObjectAtIndex:0 withObjectAtIndex:2];
NSLog(#"%#",array);
NSMutableArray *obj = [NSMutableArray arrayWithObjects:#"1",#"2",#"3",nil];
[obj exchangeObjectAtIndex:0 withObjectAtIndex:obj.count - 1];
NSLog(#"%#",obj);
I have a large mutable array with lots of duplicate values in alphabetical order.
I need to be able to convert my array *Array into a new array that contains one entry for each string variant.
I am currently using:
NSArray *array = [NSArray arrayWithObjects:papersObject.paperSubject, nil];
NSCountedSet *paperSet = [[NSCountedSet alloc] initWithArray:array];
NSMutableArray *namesArray = [[NSMutableArray alloc] initWithCapacity:[array count]];
[namesSet enumerateObjectsUsingBlock:^(id obj, BOOL *stop){
if ([paperSet countForObject:obj] == 1) {
[namesArray addObject:obj];
}
}];
NSLog(#"%#", namesArray);
But this returns a long list of the same array, still with duplicates.
Any ideas?
What about:
NSArray *arrayWithNoDuplicates = [[NSSet setWithArray:papersObject.paperSubject] allObjects];
A. What is namesSet? paperSet?
B. However:
NSOrderedSet *set = [NSOrderedSet orderedSetWithArray:array];
NSArray *arrayWithUniquesIsAnOrderedSet = set.array;
BTW: I would highly recommend to use an ordered set instead of an array, because an array with unique objects is an ordered set.
I need help with the following:
I have an NSArray with NSStrings, I want to loop thru these strings and find a matching string, when match is found the strings after this match will be extracted into an NSDictionary until a certain other match is hit.
Here is an example:
NSArray *array = #[#"Fruit",#"Apple",#"Vegtable",#"Tomato",#"Fruit",#"Banana",#"Vegtable",#"Cucumber"];
So I want to loop thru this array and split it in 2 arrays one for fruit and one for vegetable.
Anyone can help with the logic?
Thanks
This is probably the simplest way to solve the problem:
NSArray *array = #[#"Chair",#"Fruit",#"Apple",#"Orange",#"Vegetable",#"Tomato",#"Fruit",#"Banana",#"Vegetable",#"Cucumber"];
NSMutableArray *fruitArray = [NSMutableArray array];
NSMutableArray *vegetableArray = [NSMutableArray array];
NSMutableArray *currentTarget = nil;
for (NSString *item in array)
{
if ([item isEqualToString: #"Fruit"])
{
currentTarget = fruitArray;
}
else if ([item isEqualToString: #"Vegetable"])
{
currentTarget = vegetableArray;
}
else
{
[currentTarget addObject: item];
}
}
In one iteration over the array, you just keep adding items to a result array using a pointer to one of two result arrays according to the last occurrence of the #"Fruit" or #"Vegetable" string.
This algorithm ignores all items before the first occurrence of the #"Fruit" or #"Vegetable" string, because the currentTarget is initialized to nil, which ignores the addObject: messages. If you want different behaviour, just change the initialization.
You said you wanted the results in a NSDictionary, but didn't specify what should be the key. If you want one NSDictionary with two keys, Fruit and Vegetable, and values NSArrays containing the items, just use the arrays previously created:
NSDictionary *dict = #{ #"Fruit": fruitArray, #"Vegetable": vegetableArray };
PS: You have a typo in your example, Vegtable instead of Vegetable. I corrected it in my code, so keep it in mind.
If I completely understand you:
NSArray *array = #[#"Fruit",#"Apple",#"Vegtable",#"Tomato",#"Fruit",#"Banana",#"Vegtable",#"Cucumber"];
NSMutableArray *fruits = [NSMutableArray array];
NSMutableArray *vegtables = [NSMutableArray array];
for (NSInteger i = 0; i < array.count; ++i){
if ([array[i] isEqualToString:#"Fruit"]){
++i;
[fruits addObject:array[i]];
}
else if ([array[i] isEqualToString:#"Vegtable"]){
++i;
[vegtables addObject:array[i]];
}
}
Is there a one-liner to do the following
NSMutableArray *allpoints = [[NSMutableArray alloc] init];
for (NSMutableArray *arr in self.points)
[allpoints addObjectsFromArray:arr];
I have an array of arrays (self.points) and I am joining all of the objects in the subarrays into a single array.
NSArray *array1 = #[ #"a", #"b", #"c" ];
NSArray *array2 = #[ #"d", #"e", #"f" ];
NSArray *array3 = #[ array1, array2 ];
NSArray * flattenedArray = [array3 valueForKeyPath:#"#unionOfArrays.self"];
NSLog(#"flattenedArray: %#", flattenedArray);
Output:
flattenedArray: (
a,
b,
c,
d,
e,
f
)
There is not a way to add all objects in an array of arrays (e.g., every NSMutableArray in self.points to another array without iterating through.
However, you could add a category to NSArray to do exactly what you're doing now, and then call it with one line later.
If you are initializing the array and adding objects at the same time then there is an initializer for that.
NSMutableArray *allpoints = [[NSMutableArray alloc] initWithArray:self.points];
If you already have the mutable array defined and you want to just append objects to the end then you can use the following.
[allpoints addObjectsFromArray:self.points];
I don't think there is a way to do this.
NSMutableArray *allpoints = [[NSMutableArray alloc] initWithArray:self.points]
would give you an array of the arrays, but there is no single line solution. I'd suggest writing a category that will do this for you so you can easily reuse it.
According to NSArray class reference there are 4 type of methods to sort array:
1- sortedArrayUsingComparator:
2- sortedArrayUsingSelector:
3- sortedArrayUsingFunction:context:
4- sortedArrayUsingDescriptors:
For first three methods it mentioned :
The new array contains references to the receiving array’s elements, not copies of them.
But for the forth method (descriptor) it mentioned:
A copy of the receiving array sorted as specified by sortDescriptors.
But following example shows like the other 3 methods, descriptor also retain original array and do not return a new copy of it:
NSString *last = #"lastName";
NSString *first = #"firstName";
NSMutableArray *array = [NSMutableArray array];
NSDictionary *dict;
NSMutableString *FN1= [NSMutableString stringWithFormat:#"Joe"];
NSMutableString *LN1= [NSMutableString stringWithFormat:#"Smith"];
NSMutableString *FN2= [NSMutableString stringWithFormat:#"Robert"];
NSMutableString *LN2= [NSMutableString stringWithFormat:#"Jones"];
dict = [NSDictionary dictionaryWithObjectsAndKeys: FN1, first, LN1, last, nil];
[array addObject:dict];
dict = [NSDictionary dictionaryWithObjectsAndKeys: FN2, first, LN2, last, nil];
[array addObject:dict];
// array[0].first = "Joe" , array[0].last = "Smith"
// array[1].first = "Robert" , array[1].last = "Jones"
NSSortDescriptor *lastDescriptor =[[NSSortDescriptor alloc] initWithKey:last
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)];
NSSortDescriptor *firstDescriptor =[[NSSortDescriptor alloc] initWithKey:first
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)];
NSArray *descriptors = [NSArray arrayWithObjects:lastDescriptor, firstDescriptor, nil];
NSArray *sortedArray = [array sortedArrayUsingDescriptors:descriptors];
// array[1] == sortedArray[0] == ("Robert" , "Jones")
// comparing array entries whether they are same or not:
NSLog(#" %p , %p " , [array objectAtIndex:1] , [sortedArray objectAtIndex:0] );
// 0x10010c520 , 0x10010c520
it shows objects in both arrays are same,
"A copy of the receiving array sorted as specified by sortDescriptors" means that the array object is copied not the elements in the array. The reason the documentation uses the word "copy" is to make it clear that the returned array is not the same array instance as the receiver.
Elements in an array are never copied in Cocoa with the exception of initWithArray:copyItems:YES which will copy the first level items in the original array to the new array. Even then, this copy is done by calling copyWithZone: on the elements, so caveats apply depending on what elements are in your array.
Note that Cocoa is reference counted, so the concept of "deep copies" is not inherently built in for a reason. This is also (in part) the reason why array objects in cocoa come in two flavors (NSArray and NSMutableArray) and are usually immutable (NSArray) instead of as in other languages where there is not usually a concept of immutable and mutable arrays.
see this SO answer for how to get a "deep copy" of an NSArray.