Very simple problem, I am on the right track, I have to use predicates but couldn't find the solution.
I have two arrays:
A = [1, 2, 3, 4]
B = [1, 2]
I want to have an aray C = A \ B that is
C = [3, 4]
Use the right tool for the task. What you're describing here is the set operation "difference".
NSMutableSet *first = [NSMutableSet setWithObjects:#1, #2, #3, #4, nil];
NSSet *second = [NSSet setWithObjects:#1, #2, nil];
[first minusSet:second];
If you really really really need to work with arrays, you can convert between arrays and sets too:
NSArray *array = [someSet allObjects];
or
NSSet *set = [NSSet setWithArray:someArray];
You can achieve it with removeObjectsFromArray:
NSArray * arrayA = #[ #1, #2, #3, #4 ];
NSArray * arrayB = #[ #1, #2 ];
NSMutableArray * arrayC = [arrayA mutableCopy];
[arrayC removeObjectsInArray:arrayB];
EDIT
As suggested in the comments and also proposed by H2CO3, if you don't have a valid reason to use NSArray, the most convenient solution is to change data structure and switch to NSSet, which has the support for set difference, using the method -minusSet:.
EDIT 2
As Sven noted in the comments, your objects must respond properly to hash and isEqual: in order to use removeObjectsInArray:. In the above example everything will work just fined, since NSNumber has a default implementation for those methods, but in case you're using a custom class you need to explicitly override them.
Here's another approach:
NSArray * arrayA = #[ #1, #2, #3, #4 ];
NSArray * arrayB = #[ #1, #2 ];
NSIndexSet *indexSet = [arrayA indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
if([arrayB containsObject:obj]){
return NO;
}
else{
return YES;
}
}];
NSArray *arrayC = [arrayA objectsAtIndexes:indexSet];
Related
I've NSArray with NSArray in. I would like to get all NSArray into one.
I think there is a simple function to use, isn't it ?
Here is what I receive :
(
(
n0eGi1KJWq,
KHGeW32548,
),
(
n0eGi1KJWq
)
)
I would like to get :
(
n0eGi1KJWq,
KHGeW32548,
n0eGi1KJWq
)
A simply loop can be used to create a new array:
NSArray *mainArray = ... // the array containing the other arrays
NSMutableArray *finalArray = [NSMutableArray array];
for (NSArray *innerArray in mainArray) {
[finalArray addObjectsFromArray:innerArray];
}
At this point finalArray will have all of the objects from all of the other arrays.
You can also use #unionOfArrays for this purpose:
NSArray *flatArray = [array valueForKeyPath: #"#unionOfArrays.self"];
If you need a deeper flattening (for three dimensional array), use it twice:
NSArray *flatArray = [array valueForKeyPath: #"#unionOfArrays.self.#unionOfArrays.self"];
I want to get the Collection of a Specific Property from an array dictionary which has an array of values. Following is my array NSDictionaries:
NSArray *arrGroupsFromServer= #[
#{#"Id": #"7d1021ba-e9be-40c1-a0a1-ad2a2d185b74",#"Name": #"1",#"modifiedDate": #"2016-01-29T15:39:57.000Z",#"PupilIdCollection":#[#"1",#"2"]},
#{#"Id": #"4d830b79-f447-4ad7-8de1-063acf3e242c",#"Name": #"2 TEST",#"modifiedDate": #"2016-01-29T15:39:57.000Z",#"PupilIdCollection":#[#"1",#"3"]},
#{#"Id": #"e481987d-fde8-4a6b-8e05-73877065236d",#"Name": #"CQ",#"modifiedDate": #"2016-01-29T15:39:57.000Z",#"PupilIdCollection":#[#"1",#"4"]},
#{#"Id": #"1a44989d-8b3f-4d8e-8c74-a09c893ca02d",#"Name": #"Intervention group Number",#"modifiedDate": #"2016-01-29T15:39:57.000Z",#"PupilIdCollection":#[#"1",#"5"]},
#{#"Id": #"f10f2fe0-b575-450d-ad63-10d0e8fbe097",#"Name": #"EYFS Caterpillars",#"modifiedDate": #"2016-01-29T15:39:57.000Z",#"PupilIdCollection":#[#"1",#"6"]},
#{#"Id": #"232168c1-73a4-4bbb-b9a2-58e6765e4b2c",#"Name": #"Guided Reading group",#"modifiedDate": #"2016-01-29T15:39:57.000Z",#"PupilIdCollection":#[#"1",#"6"]},
#{#"Id": #"1e9b66f7-c4a7-4774-b062-ce23f587a319",#"Name": #"HfL",#"modifiedDate": #"2016-01-29T15:39:57.000Z",#"PupilIdCollection":#[#"1",#"7"]},
#{#"Id": #"62d53fc5-1fbf-4ebe-bc52-d07ec2680c66",#"Name": #"Red Intervention group",#"modifiedDate": #"2016-01-29T15:39:57.000Z",#"PupilIdCollection":#[#"1",#"8"]},
#{#"Id": #"a70e7429-996a-46ff-aff7-1e1bc5e17c3b",#"Name": #"SEN Green group",#"modifiedDate": #"2016-01-29T15:39:57.000Z",#"PupilIdCollection":#[#"1",#"9"]},
#{#"Id": #"44441c6f-843b-4933-9191-1f3afb23b6cf",#"Name": #"STAT",#"modifiedDate": #"2016-01-29T15:39:57.000Z",#"PupilIdCollection":#[#"1",#"2"]},
#{#"Id": #"04aedc28-4706-49a1-8bbd-9d58179cfd55",#"Name": #"TIST",#"modifiedDate": #"2016-01-29T15:39:57.000Z",#"PupilIdCollection":#[#"1",#"2"]},
#{#"Id": #"c98f592e-4adc-4d9d-a484-ae5b417f11db",#"Name": #"Year 8",#"modifiedDate": #"2016-01-29T15:39:57.000Z",#"PupilIdCollection":#[#"1",#"2"]}
];
Now I want to collect the PupilIdCollection Property into one single array with the DistintctUnion of all the values as follows:
NSArray * PupilIdCollection=#[#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9"];(e.g. Order doesn't matter)
I have tried it the following way:
NSArray *arrPupilsIdsFromServer = [arrGroupsFromServer valueForKeyPath:#"#distinctUnionOfObjects.PupilIdCollection"];
But this only gives me different Objects of PupilIdCollection in an array of arrPupilsIdsFromServer rather than the one object with the array of all the values in one array as following:
I want something like the following in just one line of code in KVC:
NSArray * PupilIdCollection=PupilIdCollection=#[#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9"];(e.g. Order doesn't matter);(e.g. Order doesn't matter)
How to do this?
You need to use the #distinctUnionOfArrays instead of the #distinctUnionOfObjects. This operator helps flattening hierarchies of collections, and merge sub-arrays. See the developer documentation for details.
For example, these lines (used on your very NSArray)
NSArray *arrPupilsIdsFromServer = [arrGroupsFromServer valueForKeyPath:#"#distinctUnionOfArrays.PupilIdCollection"];
NSLog(#"\nPupil Ids From Server:%#", arrPupilsIdsFromServer);
Yield this output:
Pupil Ids From Server:(
1,
2,
3,
4,
5,
6,
7,
8,
9
)
from wain's answer you can do it after getting the values of PupilIdCollection for example,
NSArray *pupilIdCollection = [arrGroupsFromServer valueForKeyPath:#"PupilIdCollection"];
__block NSMutableSet *mutableSet = [[NSMutableSet alloc] init];
[pupilIdCollection enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[mutableSet addObjectsFromArray:obj];
}];
pupilIdCollection = [mutableSet allObjects];
NSLog(#"all objects-%#",pupilIdCollection);
Wain has explained it very well. I too feel that it would be very difficult to achieve in a single line. You can create a single array for all those elements and then use distinctUnionOfObjects.
NSMutableArray *singleArray =[NSMutableArray array];
for (NSDictionary *d in arrGroupsFromServer) {
[singleArray addObjectsFromArray:[d objectForKey:#"PupilIdCollection"]];
}
NSArray *pupilIdCollection = [singleArray valueForKeyPath:#"#distinctUnionOfObjects.self"];
I have an array of strings like such:
NSArray *unsortedArray = [NSArray arrayWithObjects:#"MailIn", #"Branch", #"eSign", #"RDC", nil];
I receive this array and it is not gauranteed that all 4 strings will be present. It could have all 4, or only 1.
I need to sort the array in this exact order all the time.. [eSign, RDC, Branch, MailIn]. Keep in mind that there is a chance where one or more of these may not be present. How do I achieve this?? Any help would be greatly appreciated. Thanks in advance!
If you really want a sort then here is a way to do that. But for only 4 strings I'd likely just unroll #Zev Eisenberg's loop and build it up in code.
NSDictionary* indexes = #{ #"eSign" : #0, #"RDC" : #1, #"Branch" : #2, #"MailIn" : #3 };
NSArray* sorted = [unsorted sortedArrayUsingComparator: ^NSComparisonResult(NSString* s1, NSString* s2) {
return [indexes[s1] compare: indexes[s2]];
}];
I would build a new array, using the exemplar array as a template:
NSArray *exemplarArray = #[ #"eSign", #"RDC", #"Branch", #"MailIn" ];
NSArray *unsorted = #[ #"MailIn", #"Branch", #"eSign", #"RDC" ];
NSMutableArray *sorted = [NSMutableArray array];
for (NSString *string in exemplarArray) {
if ([unsorted containsObject:string]) {
[sorted addObject:string];
}
}
NSLog(#"%#", sorted);
I got 2 arrays of strings:
NSArray * current = #[#"1", #"6", #"53"];
NSArray * new = #[#"1", #"626", #"53", #"13"];
I want to get number 6 in array, and numbers 626 and 13 in second array
(I want data that is in first array but there is not in second, and conversely)
NSMutableSet * newSet = [NSMutableSet setWithArray:new];
[newSet minusSet:[NSSet setWithArray:current ]];
NSArray * result1 = [NSArray arrayWithSet:newSet];
NSArray * result2 = ?
I not get it, I know that is very simple question, but I have no ideas
Your code contains a lot of syntax errors.
Please post actual code, I understand the issue you are talking about, that's why I'm posting this answer. Please post questions with valid code, else you won't get proper answer (Only get downvotes)
Use the following code:
NSArray *current = #[#"1", #"6", #"53"];
NSArray *newArr = #[#"1", #"626", #"53", #"13"];
NSMutableSet *newSet = [NSMutableSet setWithArray:newArr];
[newSet minusSet:[NSSet setWithArray:current]];
NSArray * result1 = [NSArray arrayWithObjects:[newSet allObjects],nil];
// result 1 will have 626 and 13
newSet = [NSMutableSet setWithArray:current];
[newSet minusSet:[NSSet setWithArray:newArr]];
NSArray * result2 = [NSArray arrayWithObjects:[newSet allObjects],nil];
// result 2 will have 6
// Create arrays of the IDs only
NSArray *notiCloudIDs = [notiCloud valueForKey:#"id"];
NSArray *notiLocIDs = [notiLoc valueForKey:#"id"];
// Turn the arrays into sets and intersect the two sets
NSMutableSet *notiCloudIDsSet = [NSMutableSet setWithArray:notiCloudIDs];
NSMutableSet *notiLocIDsSet = [NSMutableSet setWithArray:notiLocIDs];
[notiCloudIDsSet intersectSet:notiLocIDsSet];
// The IDs that are now in notiCloudIDsSet have been present in both arrays
NSLog(#"Duplicate IDs: %#", notiCloudIDsSet);
This will give you the common elements in the two. You can then delete the common elements from array1.
This question already has answers here:
The best way to remove duplicate values from NSMutableArray in Objective-C?
(14 answers)
Closed 9 years ago.
i have a nsmutablearray as is shown below. I would like to retrieve list value without redundancy. in this example i should retrive 10 20 30
NSMutableArray *array = [[NSMutableArray alloc]initWithObjects:#"10",#"20",#"30",#"30",#"30",#"30",#"20", nil];
Transform the array into a set, and then back into an array.
NSSet *set = [NSSet setWithArray:array];
NSArray *a = [set allObjects];
You can also have this new array sorted:
NSArray *a2 = [a sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2];
}];
Since iOS 5 you can use -[NSOrderedSet orderedSetWithArray:] which preserves the order:
NSArray *a2 = [[NSOrderedSet orderedSetWithArray:array] array];
NSArray *withRedunecy = [[NSSet setWithArray: array] allObjects];
This will be the one way like you can create new NSArray which has no duplicate objects or you need to create a logic for getting unique objects like insert one by one with checking is it already present or not.
Try to use this on
NSArray *array = #[#"10",#"20",#"30",#"30",#"30",#"30",#"20"];
NSArray *newArray = [[NSSet setWithArray:array] allObjects];
NSLog(#"%#", newArray);
Output :
(
30,
20,
10
)
Only this line of code will work fine .
NSSet *mySet = [NSSet setWithArray:array];
now mySet will have unique elements.so create array with this set
NSArray *myarray = [mySet allObjects];