How to get the object that existed in all NSArray - ios

I have multiple arrays, for example:
NSArray *a = #[#"a", #"b", #"c"];
NSArray *b = #[#"d", #"a", #"e"];
NSArray *c = #[#"i", #"f", #"a"];
As you can see "a" is exist in array a, b, c. I would like to make a function that return the same objet in supplied arrays. So, like this one, I want to get this "a" from them. if all arrays don't have the same object, which will return nil. For example "f" only exist in c, so the function should return nil.

NSMutableSet *set = [NSMutableSet new];
NSMutableSet *set1 = [NSMutableSet setWithArray:a];
NSMutableSet *set2 = [NSMutableSet setWithArray:b];
NSMutableSet *set3 = [NSMutableSet setWithArray:c];
set = [set1 intersectSet:set2];
set = [set intersectSet:set3];
NSArray *allArray = [set allObjects];

NSMutableSet *intersection = [NSMutableSet setWithArray:a];
[intersection intersectSet:[NSSet setWithArray:b]];
[intersection intersectSet:[NSSet setWithArray:c]];
NSArray *intersecArray = [intersection allObjects];
this work! from your code it return a in result array

- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *a = #[#"a", #"b", #"c"];
NSArray *b = #[#"d", #"a", #"e"];
NSArray *c = #[#"i", #"f", #"a"];
NSArray *arraydOfAll=[NSArray arrayWithObjects:a,b,c,nil];
NSArray *commonObjArray=[self intersectArray:arraydOfAll];
}
-(NSArray *)intersectArray:(NSArray *)allArray{
NSMutableSet *set1 = [NSSet setWithArray:[allArray objectAtIndex:0]];
for (NSInteger i=1;i<allArray.count : i++){
[set1 intersectSet:[NSSet setWithArray:[allArray objectAtIndex:i]];
}
return [set1 allObjects]
}

Related

How to concatenate two mutable array like one element of first array and first element of second array in objective c

I am new in iOS.And I am doing like this
NSMutableArray* arr1 = [NSMutableArray arrayWithObjects: #"A", #"C", #"E", nil];
NSMutableArray* arr2 = [NSMutableArray arrayWithObjects: #"B", #"D", #"F", nil];
NSMutableArray* animals = [NSMutableArray arrayWithArray:arr1];
[animals addObjectsFromArray: arr2];
It give me output like
ACEBDE
But I need output like
ABCDEF
Any Hint
Just loop them
NSMutableArray* arr1 = [NSMutableArray arrayWithObjects: #"A", #"C", #"E", nil];
NSMutableArray* arr2 = [NSMutableArray arrayWithObjects: #"B", #"D", #"F", nil];
NSMutableArray* animals = [NSMutableArray new];
NSUInteger maxCount = arr1.count > arr2.count ? arr1.count : arr2.count;
for (int i = 0; i < maxCount; i ++) {
if ([arr1 objectAtIndex:i]) {
[animals addObject:[arr1 objectAtIndex:i]];
}
if ([arr2 objectAtIndex:i]) {
[animals addObject:[arr2 objectAtIndex:i]]
}
}
This will work for all types of arrays.
I tried now.I got it.Check the below answer.You have to use sortDescriptor simply.
NSMutableArray* arr1 = [NSMutableArray arrayWithObjects: #"A", #"C", #"E", nil];
NSMutableArray* arr2 = [NSMutableArray arrayWithObjects: #"B", #"D", #"F", nil];
NSMutableArray* animals = [NSMutableArray arrayWithArray:arr1];
[animals addObjectsFromArray: arr2];
NSArray *sortedArray = [animals sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSLog(#"The sortedArrays are - %#",sortedArray);
The printed results are
The sortedArrays are - (
A,
B,
C,
D,
E,
F
)
try this -
NSMutableArray* arr1 = [NSMutableArray arrayWithObjects: #"A", #"C", #"E", nil];
NSMutableArray* arr2 = [NSMutableArray arrayWithObjects: #"B", #"D", #"F", nil];
NSUInteger maxCount = arr1.count > arr2.count ? arr1.count : arr2.count;
NSMutableArray* animals = [[NSMutableArray alloc] init];
for (int i=0; i<maxCount; i++)
{
if (i<arr1.count) {
[animals addObject:[arr1 objectAtIndex:i]];
}
if (i<arr2.count) {
[animals addObject:[arr2 objectAtIndex:i]];
}
}
Adding another answer just for fun.
NSMutableArray* arr1 = [NSMutableArray arrayWithObjects: #"A", #"C", #"E", nil];
NSMutableArray* arr2 = [NSMutableArray arrayWithObjects: #"B", #"D", #"F", nil];
NSMutableArray* animals = [NSMutableArray new];
NSInteger minCount;
NSMutableArray *maxArray;
if (arr1.count < arr2.count) {
minCount = arr1.count;
maxArray = arr2;
}
else {
minCount = arr2.count;
maxArray = arr1;
}
for (int i = 0; i < minCount; i++) {
[animals addObject:arr1[i]];
[animals addObject:arr2[i]];
}
NSInteger pendingItemsLength;
if ((pendingItemsLength = maxArray.count - minCount)) {
[animals addObjectsFromArray:[maxArray subarrayWithRange:NSMakeRange(minCount, pendingItemsLength)]];
}
This is efficient than the accepted answer as it avoids if condition inside a for loop.

Predicate insensitive search for two array of strings

I am trying to get common values from two array but insensitive match.But cannot succeed.Whats wrong with the predicate.
NSMutableArray *tempArray1 = [NSMutableArray arrayWithObjects:#"apple", #"cat", nil];
NSMutableArray *tempArray2 = [NSMutableArray arrayWithObjects:#"APPLE", #"CAT", nil];
// NSPredicate *resultPredicate1 = [NSPredicate predicateWithFormat:#"SELF IN [cd] %#", tempArray1];
NSPredicate *resultPredicate1 = [NSPredicate predicateWithFormat:#"SELF [cd] IN %#", tempArray1];
NSMutableArray *arr_filteredtest = [NSMutableArray arrayWithArray:[tempArray2 filteredArrayUsingPredicate:resultPredicate1]];
NSLog(#"%lu",(unsigned long)arr_filteredtest.count);
If you want case insensitive unique set from your two arrays, first you have to either lowercase or uppercase all the strings, and then create NSSet :
NSMutableArray *joindArr = [NSArray arrayWithArray:tempArray1, nil];
[joindArr addObjectsFromArray:tempArray2];
NSMutableArray *arr1 = [[NSMutableArray alloc]init]; //make a nsmutableArray
for (int i = 0; i<[arr count]; i++) {
[arr1 addObject:[[arr objectAtIndex:i]lowercaseString]];
}
NSSet *set = [NSSet setWithArray:(NSArray*)arr1];//this set has unique values
You can achieve intersection using NSSet, unfortunately the search using NSSet is case sensitive.
1.So convert both the arrays to common case, either upperCase or lowerCase
2.Use intersectSet to get result
Example:
NSMutableArray *tempArray1 = [NSMutableArray arrayWithObjects:#"apple", #"cat", nil];
NSMutableArray *tempArray2 = [NSMutableArray arrayWithObjects:#"APPLE", #"CAT", nil];
tempArray2 = [self convertStringObjectsToLoweCase:tempArray2]; //convert all elements to lower case/ upper case
NSSet *set1 = [NSSet setWithArray:tempArray1];
NSSet *set2 = [NSSet setWithArray:tempArray2];
NSMutableSet *mutableSet = [NSMutableSet setWithSet:set1]; //Initialize with parent array,usually array with more elements
[mutableSet intersectSet:set2];
NSArray *arrayContainingCommonObjects = [mutableSet allObjects];
NSLog(#"arrayContainingCommonObjects : %#",arrayContainingCommonObjects);
Use the following helper method
- (NSMutableArray *)convertStringObjectsToLoweCase:(NSMutableArray *)inputArray
{
[inputArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isKindOfClass:[NSString class]]) {
NSString *loweCaseString = [(NSString *)obj lowercaseString];
[inputArray replaceObjectAtIndex:idx withObject:loweCaseString];
}
}];
return inputArray;
}
Output:
arrayContainingCommonObjects : (
apple,
cat )
I think you should to try this one
NSMutableArray *tempArray1 = [NSMutableArray arrayWithObjects:#"apple", #"cat", nil];
NSMutableArray *tempArray2 = [NSMutableArray arrayWithObjects:#"apple", #"CAT", nil];
NSMutableSet *intersection = [NSMutableSet setWithArray:tempArray1];
[intersection intersectSet:[NSSet setWithArray:tempArray2]];
NSArray *NEW_ARR = [intersection allObjects];
NSLog(#"new arry:: %#",NEW_ARR);

Trying to store data in an 2d array in objective c

I have code that works but then I would have to add a new array and new code for every new country that my app will support and it is probably highly inefficient, as this code has to be run before the app starts and the view appears.
- (NSMutableDictionary *)retrieveDictionaryOfCountryAndCompany {
NSMutableDictionary *companyAndCountry = [[NSMutableDictionary alloc] init];
NSMutableArray *countryNames = [[NSMutableArray alloc] init];
NSMutableArray *germanyArray = [[NSMutableArray alloc] init];
NSMutableArray *englandArray = [[NSMutableArray alloc] init];
PFQuery *companyQuery = [PFQuery queryWithClassName: #"Company"];
NSArray *objects = [companyQuery findObjects];
for (PFObject *object in objects) {
if ([[object valueForKey:#"country"] isEqual: #"Germany"]) {
[germanyArray addObject:[object valueForKey:#"name"]];
}
[countryNames addObject:[object valueForKey:#"country"]];
}
NSSet *uniqueItems = [NSSet setWithArray:germanyArray];
germanyArray = [[uniqueItems allObjects] mutableCopy];
uniqueItems = [NSSet setWithArray:countryNames];
countryNames = [[uniqueItems allObjects] mutableCopy];
[germanyArray sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
[countryNames sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
[companyAndCountry setObject:germanyArray forKey:#"Germany"];
[companyAndCountry setObject:countryNames forKey:#"country"];
return companyAndCountry;
}
Is there a better solution that I'm not seeing because it's too simple? Thanks for your help.
Unless I'm being dense:
- (NSMutableDictionary *)retrieveDictionaryOfCountryAndCompany {
NSMutableArray *countryNames = [NSMutableArray array];
NSMutableDictionary *companyAndCountry =
[#{ #"country" : countryNames } mutableCopy];
PFQuery *companyQuery = [PFQuery queryWithClassName: #"Company"];
NSArray *objects = [companyQuery findObjects];
for (PFObject *object in objects) {
NSString *countryName = [object valueForKey:#"country"];
NSString *placeName = [object valueForKey:#"name"];
if(!countryName || !placeName) continue; // a malformed record
[countryNames addObject:countryName];
NSMutableSet *namesInCountry = companyAndCountry[countryName];
if(!namesInCountry)
{
namesInCountry = [NSMutableSet set];
companyAndCountry[countryName] = namesInCountry;
}
[namesInCountry addObject:placeName];
}
for (NSString *key in [[companyAndCountry allKeys] copy])
{
NSArray *sortedArray =
[[companyAndCountry[key] allObjects]
sortedArrayUsingSelector:
#selector(localizedCaseInsensitiveCompare:)];
companyAndCountry[key] = sortedArray;
}
return companyAndCountry;
}
So just create and populate the lists on demand, initially as sets to avoid some of the array -> set -> array -> sorted array shuffle at the end.
As to performance, Parse is a web service so this should all be done asynchronously. Is that the case?

How to sort the values of one NSMutableArray using the value of another NSMutableArray?

I have one NSMutableArray *arr1 with values:
{(B,abc) (E,pqr) (C,xyz)}
and another NSMutableArray *arr2 with
{(B) (C) (E)}.
Now i want to sort arr1 using arr2 value so that arr1 becomes {(B,abc) (C,xyz) (E,pqr)}. How can i do this?
So, it seems you have an array and an array of arrays:
NSArray *sorter = #[#"B", #"C", #"E"];
NSMutableArray *sortee = [#[
#[#"B", #"abc"],
#[#"E", #"pqr"],
#[#"C", #"xyz"]
] mutableCopy];
[sortee sortUsingComparator:^(id o1, id o2) {
NSString *s1 = [o1 objectAtIndex:0];
NSString *s2 = [o2 objectAtIndex:0];
NSInteger idx1 = [sorter indexOfObject:s1];
NSInteger idx2 = [sorter indexOfObject:s2];
return idx1 - idx2;
}];
Try this,
NSMutableArray *unsortedArray = [NSMutableArray arrayWithObjects:[NSArray arrayWithObjects:#"B",#"abc", nil],[NSArray arrayWithObjects:#"E",#"pqr", nil],[NSArray arrayWithObjects:#"C",#"xyz", nil],nil];
NSArray *guideArray = [NSArray arrayWithObjects:#"B",#"C",#"E", nil];
for(int i=0; i< [guideArray count];i++)
{
for(int j=0; j< [unsortedArray count];j++)
{
if([[unsortedArray objectAtIndex:j] containsObject:[guideArray objectAtIndex:i]])
{
[unsortedArray exchangeObjectAtIndex:j withObjectAtIndex:i];
break;
}
}
}
NSLog(#"%#",unsortedArray);
I have tested this and working for me. Hope this helps you.

how to capture the first letter of each array entry

I have a sorted array of NSString values, I would like to know how to capture the first letter of each string only when the first letter is different and put it in a new NSArray.
For instance if I have an array that was like like
"a, aaa, aaaa, b, c, d, dd, ddd"
it would be like this in the new NSArray
"a, b, c, d"
Any help would be greatly appreciated.
Something like this:
- (NSArray *)indexLettersForStrings:(NSArray *)strings {
NSMutableArray *letters = [NSMutableArray array];
NSString *currentLetter = nil;
for (NSString *string in strings) {
if (string.length > 0) {
NSString *letter = [string substringToIndex:1];
if (![letter isEqualToString:currentLetter]) {
[letters addObject:letter];
currentLetter = letter;
}
}
}
return [NSArray arrayWithArray:letters];
}
NSString+LetterIndex.h
#interface NSString (LetterIndex)
#property (nonatomic, readonly) NSString * firstLetter;
#end
NSString+LetterIndex.m
#implementation NSString (LetterIndex)
- (NSString *)firstLetter
{
return self.length ? [self substringToIndex:1] : #"";
}
your method:
- (NSArray *)indexLettersForStrings:(NSArray *)strings {
NSSet * distinctValues = [NSSet setWithArray:[strings valueForKey:#"firstLetter"]];
return [[distinctValues allObjects] sortedArrayUsingSelector:#selector(compare:)]
}
also if you have some objects of custom class and want to group them by first letters of some string parameter, you can use this:
NSSet * distinctValues = [NSSet setWithArray:[objects valueForKeyPath:#"myStringParam.firstLetter"]];
NSArray *array = [NSArray arrayWithObjects:#"a", #"aaa", #"aaaa",#"b", #"c", #"d", #"dd", #"ddd", nil];
BOOL control = YES;
NSMutableArray *array2 = [NSMutableArray array];
for (int i = 0; i<array.count; i++) {
for (int j = 0; j<array2.count;j++){
if ([[array2 objectAtIndex:j]isEqualToString:[[array objectAtIndex:i]substringToIndex:1]]){
control = NO;
}
else
control = YES;
}
if (control)
[array2 addObject:[[array objectAtIndex:i]substringToIndex:1]];
}
Try this:
NSArray *arr = #[#"a", #"aaa", #"aaaa", #"b", #"c", #"d", #"dd", #"ddd"];
NSMutableArray *newArr = [NSMutableArray array];
NSMutableSet *set = [NSMutableSet set];
for (NSString *str in arr)
{
if (![set containsObject:[str substringToIndex:1]])
[newArr addObject:[str substringToIndex:1]];
[set addObject:[str substringToIndex:1]];
}
NSLog(#"%#", newArr);
This uses a Set to keep track of occurrences that already past threw. When it doesnt exist it places them into a new array.

Resources