Combining NSArrays - objective-c

I have 3 NSArrays with:
item: amount
A: 1
B: 2
C: 3
A: 2
E: 1
F: 6
C: 5
D: 1
F: 3
After "combining" these into one, I need:
A: 3
B: 2
C: 8
D: 1
E: 1
F: 9
Do I first combine all the arrays into one and then sum and remove the duplicates?

You could use an NSCountedSet. I'm not clear on the structure of the data in your arrays, but by assuming that your B: 2 means that you have two B's in the array, then something like this would work:
NSCountedSet *set = [NSCountedSet setWithCapacity:[array1 count]+[array2 count]+[array3 count]];
[set addObjectsFromArray:array1];
[set addObjectsFromArray:array2];
[set addObjectsFromArray:array3];
// Test it out!
NSUInteger countForC = [set countForObject:objC];
// countForC == 8

Instead of using a NSArray you could try using a NSMutableDictionary where the key is inherent in the objects structure. That will allow you to iterate through each of your arrays of letters and counts then query for the value with the key, get the value and add to the value, then continue processing.

One possibility would be to use:
Use predicates to extract like sets of data (by item) into separate arrays. See Collection predicates guide
Key Value Coding to sum the value field of each of the resulting arrays (by item). See KVO collection operators.
Pop the results in whatever structure you like (NSArray or NSDictionary).
There may be performance considerations to explore. Alternatively, iterate the array, pulling out matching items in a separate NSDictionary (keyed on item) and summing as you go.

Related

Octave: is there a way of searching items in a cell array containing scalar structure with fields and how to define the conditions

I have this array in Octave :
dwnSuccess(1,1)
ans =
{
[1,1] =
scalar structure containing the fields:
site = FRED
interval = d
aard = logDir log/
dwnGrootte = log/
time = 737861.64028
and I would like to formulate conditions to find cells containing e.g. logDir in the field 'aard'.
I don't find the correct syntax. Someone knows where to find or has an example with combinations of conditions. Thanks
Assuming that you need to keep a cell array of scalar structs (instead of a struct array which makes more sense if each struct has a defined set of fieldnames), then you need to iterate the cell array to get that field and then use logical indexing to create a new cell array with the structs of interest. Like so:
aards = cellfun (#getfield, cs, {"aard"}, "UniformOutput", false);
m = strcmp(aards, "logDir"); # this must match the whole string
filter_cs2 = cs(m);
If you are interested on finding whether a string is somewhere in that field, then it's just a bit more complex:
m = ! cellfun ("isempty", strfind (aards, "logDir"));
If I understood correctly your question, then suppose you have the following cell array:
a = cell();
a{1} = struct('a', 1, 'b', 'dwn', 'c', 2);
a{2} = struct('a', 2, 'b', 'notdwn', 'c', 3);
a{3} = struct('a', 3, 'b', 'dwn', 'c', 4);
a{4} = struct('a', 4, 'b', 'dwn', 'c', 5);
I think the easiest thing to do would be to first convert it to a struct array. You can do so easily via 'sequence generator' syntax, i.e.
s = [a{:}]; % collect all cell elements as a sequence, then wrap into an array
If you are in charge of this code, then I would instead just create a struct array instead of a cell array from the very beginning.
Once you have that, you can again use a 'sequence generator' syntax on the struct array, with an appropriate function that tests for equality. In your case, you could do something like this:
strcmp( {s.b}, 'dwn' )
% ans = 1 0 1 1
s.b accesses the field 'b' in each element of the struct array, returning it as a comma separated list. Wrapping this in braces causes this sequence to become a cell array. You then pass this resulting cell array of strings into strcmp, to compare each element with the string 'dwn'.
Depending on what you want to do next, you can use that logical array as an index to your struct array to isolate only the structs that contain that value etc.
Obviously this is a quick way of doing it, if you're comfortable with generating sequences in this way. If not, the general idea stands and you're welcome to iterate using traditional for loops etc.

Get key with largest value from a dictionary in Smalltalk

I am using a Dictionary where the keys are strings and the values are integers. How can I get the key with the largest value out of this Dictionary?
I know there is the associationsDo: method I can use to iterate over both keys and values, but I don't know how to get the maximum value.
| countDict |
countDict := Dictionary new.
...
countDict associationsDo: [ :k :v | ??? ]
Here is a way to do it following your idea:
| max largest |
max := nil.
countDict associationsDo: [:k :v |
(max isNil or: [v > largest])
ifTrue: [
max := k.
largest := v]].
^max
Here is another way, shorter but not very efficient:
countDict isEmpty ifTrue: [^nil].
^countDict keyAtValue: countDict max
Also, if you have a countDict I suspect that it represents the number of occurrences of every key. If that is the case you shouldn't be using a Dictionary but a Bag. Instances of Bag represent collections of objects which may have several occurrences each. Examples:
names := Bag new.
people do: [:person | names add: person firstName].
and you may end up with
2 occurrences of 'John'
1 occurrence of 'Paul'
4 occurrences of 'Ringo'
7 occurrences of 'George'
names occurrencesOf: 'John' ----> 2
The Bag will internally have a countDict sort of Dictionary, but to your model a Bag could reveal better your intention than a Dictionary because you will only need to add: elements without having to count them; the Bag will do it for you.
With a Bag your computation becomes
bag occurrencesOf: bag asSet max
The reason to send asSet is to avoid iterating several times on every value, which would happen if we simply put bag max. This simpler code will also work, but given that max iterates using do: and Bag implements do: by repeating the evaluation of the block for every occurrence of the element, this solution would be less efficient.
A better approach would be to re-implement max (and min) in Bag so that each element is iterated once. This would be similar to the code that we have above which followed your initial idea (associationsDo: [...). But let's leave the details of this as an exercise for the reader.
Anyway, if we re-implemnted max in Bag, the code would become simple and efficient at once:
bag occurrencesOf: bag max
Another nice way to do this:
(countDict associations detectMax: #value) key

Nsmutablearray insertobject atindex but move down already inserted objects

I wanted to ask if the following scenario is somehow possible to happen.
I have an Nsmutablearray and i have in it 5 objects. I load the Nsmutablearray on an uitableview. I want to insert a new object at the top of the other five objects but also move down all the previously inserted objects down by one. let me give you an example
0 one
1 two
2 three
3 four
4 five
i want to result like this after the new object inserted on the top
0 six
1 one
2 two
3 three
4 four
5 five
Any help appreciated.
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index
This method of NSMutableArray is what you are looking for.
If index is already occupied, the objects at index and beyond are shifted by adding 1 to their indices to make room.
The method you are looking for is: - [NSMutableArray insertObject:atIndex:].
In your example, the index would be 0.

Resuming and working through an array "loop" in obj-C

I'm writing an app where a group of people must mark each other. So I have a "Users" array like this:
0: paul
1: sally
2: james
3: bananaman
The first item Paul is marked (out of ten) by the other three, and then the second item Sally is marked by the other three (index 2, 3, 0) and so on, to create a "Results" array like this one:
0: paul, sally, 5
1: paul, james, 7
2: paul, bananaman, 9
3: sally, james, 4
I'm keeping track of the current 'scorer' and 'being_scored' integers as a new score gets added, which looks like this:
scorer = 1, being_scored = 0
scorer = 2, being_scored = 0
scorer = 3, being_scored = 0
scorer = 0, being_scored = 1
scorer = 2, being_scored = 1
However the group can stop scoring at any point, and a different group session could be loaded, which was also partially scored.
My question is how can I generate the 'scorer' and 'being_scored' values based only on the results [array count].
Presumably it's the [results count] divided by [users count] - 1, with the resulting whole number 'being_scored' and the remainder is the 'scorer'.
But my brain is utterly fried after a long week and this doesn't seem to be working.
Any help much appreciated
Mike.
Ignoring your added comment that the "Results" array is multi-dimensional and simply contains structs/objects with three fields/properties: scored, scorer, score; then surely you just go to the last element of "Results" (at index [Results count]-1), select the scored and scorer and move on to the next in your sequence - which you presumably have logic for already in the case the loop was not interrupted (something like "if last scorer precedes being_scored [treating the array as a circular buffer by using modulo arithmetic] then advanced being_scored and init scorer else advance scorer").
But then that sounds rather obvious, but you did say you brain was fried...
Not Ignoring your added comment implies you have a two-dimensional array of scores which you are filling up in some pattern? If this is a pre-allocated array of some number type then if you init it with an invalid score (negative maybe?) you scan the array following your pattern looking for the first invalid score and restart from there. If it is a dynamic single dimensional array of single dimensional arrays then the count of the outer one tells you the being_scored, and the count of the last inner one tells you the scorer...
But that sounds rather obvious as well...
Maybe some sleep? Then reframe the question if you're still stuck? Or maybe this bear of little brain missed the point entirely and somebody else will figure out your question for you.
[This is more a comment than an answer, but its too long for a comment, sorry.]

Comparing values In 2 different NSArray objects

I have 2 NSArray's that are holding values...
For example NSArray 1 has values 1 2 4 in it
and NSArray 2 has values 1 2 4 5 6 in it.
How can I write code to compare these 2 arrays to get the following information...
Count the values that are the same (so in this case 3) and count the values that are not the same (in this case 2).
I am simply populating the arrays like this:
NSString *s = #"1,2,4";
NSArray *numbers = [s componentsSeparatedByString:#","];
where *s is actually getting the text from a UITextField. If sorting mattering in comparing can you show me code to sort to make sure the user doesnt put the numbers in order?
If you are fine with sets instead of arrays, you can use NSMutableSet instead of NSArray. NSMutableSet has nice methods like intersectSet: and minusSet:
I would probably use the following method of the NSArray class:
enumerateObjectsUsingBlock.
and code the block testing for membership in the other array with the method:
indexOfObjectIdenticalTo.
If this isn't clear to you let me know.