I'm working on a project where I read in a comma delimited value file generated by a device. I have no control over the file and it can contain 10-20 named parameters with thousands of values for each parameter over a time period. I plan on associating the DataRecord with the time after. That is, each time will have a DataRecord associated with it. So, my code needs to be dynamic when it comes to generating the parsing data structures. I'm having trouble figuring a way to unwrap the arrays I have parsed from the raw data file. Here is an example.
#interface DataRecord : NSObject
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSArray *values;
#end
NSArray *nameArray = [[NSArray alloc] initWithObjects:
#"Analog", #"Battery", nil];
NSArray *valueArray1 = [[NSArray alloc] initWithObjects:
[NSNumber numberWithFloat:1.0f],
[NSNumber numberWithFloat:2.0f],
nil];
NSArray *valueArray2 = [[NSArray alloc] initWithObjects:
[NSNumber numberWithFloat:1.1f],
[NSNumber numberWithFloat:2.1f],
nil];
NSArray *valueArray3 = [[NSArray alloc] initWithObjects:
[NSNumber numberWithFloat:1.2f],
[NSNumber numberWithFloat:2.2f],
nil];
NSArray *valueArray4 = [[NSArray alloc] initWithObjects:
[NSNumber numberWithFloat:1.3f],
[NSNumber numberWithFloat:2.3f],
nil];
NSArray *arrayOfArrays = [NSArray arrayWithObjects:valueArray1,
valueArray2, valueArray3, valueArray4, nil];
What I'm looking to end up with is an array of Data Records,
DataRecord(0)
name: analog
values: (1.0, 1.1, 1.2, 1.3)
DataRecord(1)
name: battery
values: (2.0, 2.1, 2.2, 2.3)
Maybe I should be using Dictionaries, struct's, I'm not sure, chasing my tail.
Thank you.
Untested:
NSMutableArray *dataRecords = [NSMutableArray new];
for (NSUInteger i = 0; i < [nameArray count]; i++)
{
DataRecord *dr = [DataRecord new];
dr.name = nameArray[i];
NSMutableArray *values = [NSMutableArray new];
for (NSArray *array in arrayOfArrays)
[values addObject:array[i]];
dr.values = values;
[dataRecords addObject:dr];
}
Related
I am fresher to iOS. In my application i have 3 mutable arrays with objects like
NSMutableArray *MuteItem = [NSMutableArray alloc]initWithObjects:#"a", #"b", #"b", #"c", #"c", #"c", nil]];
NSMutableArray *MuteQuantity = [NSMutableArray alloc]initWithObjects:#"1", #"1", #"1", #"1", #"1", #"1", nil]];
NSMutableArray *MutePrice = [NSMutableArray alloc]initWithObjects:#"4", #"3", #"3", #"6", #"6", #"6", nil]];
Now i need to print that 3 mutable arrays values with counting the same item's quantity and calculate the price also like objects
MuteItem = { a, b, c }
MuteQuantity = { 1, 2, 3 } // counting of same item's quantity like {1, 1+1, 1+1+1}
MutePrice = { 4, 6, 18 } // here addition of same item's prices like {4, 3+3, 6+6+6}
So anybody, would you please help me in this problem. Thanks in advance.
This code will do exactly as you requested, and will even handle any keys in MuteItem, and will generate three new arrays with the aggregate information from each of the three original arrays.
NSMutableArray* muteItem = [[NSMutableArray alloc] initWithObjects: #"a", #"b", #"b", #"c", #"c", #"c", nil];
NSMutableArray* muteQuantity = [[NSMutableArray alloc] initWithObjects: #"1", #"1", #"1", #"1", #"1", #"1", nil];
NSMutableArray* mutePrice = [[NSMutableArray alloc] initWithObjects: #"4", #"3", #"3", #"6", #"6", #"6", nil];
NSMutableArray* setItem = [NSMutableArray array];
NSMutableArray* setQuantity = [NSMutableArray array];
NSMutableArray* setPrice = [NSMutableArray array];
NSSet* itemSet = [NSSet setWithArray: muteItem];
for (NSString* key in itemSet) {
NSIndexSet* indices = [muteItem indexesOfObjectsPassingTest: ^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return [obj isEqualToString: key];
}];
__block NSInteger totalQuantity = 0;
__block NSInteger totalPrice = 0;
[indices enumerateIndexesUsingBlock: ^void(NSUInteger idx, BOOL *stop) {
totalQuantity += [[muteQuantity objectAtIndex: idx] integerValue];
totalPrice += [[mutePrice objectAtIndex: idx] integerValue];
}];
[setItem addObject: key];
[setQuantity addObject: [NSNumber numberWithInteger: totalQuantity]];
[setPrice addObject: [NSNumber numberWithInteger: totalPrice]];
}
NOTE: This code assumes you are using ARC. Also, in your original code you forgot to nil terminate your array constructors.
EDIT: I notice that your prices are integers, you may want to change them to floats if your currency uses decimal fractions. This would require changing the definition of totalPrice to float and you would want to change the end of the totalPrice += line from integerValue to floatValue.
EDIT2: Renamed all variables that started with a capital letter as this violates standard naming convention. Only class names should begin with a capital letter, variables should always begin with lowercase, or an _ for instance variables. :)
I have one NSDictionary and one NSMutableArray And I want store many object from NSDictionary into NSMutableArray from one key but I dont know about it.
this is my code :
//NSArray * a = [[NSArray alloc]initWithObjects:#"1",#"2",#"3",#"4",#"7",#"9", nil];
//NSArray *b = [[NSArray alloc]initWithObjects:#"1",#"2",#"3",#"4",#"5",#"0", nil];
NSDictionary * dic = [NSDictionary dictionaryWithObjectsAndKeys:a,#"number1",b,#"number2", nil];
NSMutableArray *array = [NSMutableArray alloc].... ?
I want store object in number1 key from NSDictionary in NSMutableArray
Since it appears that you store arrays as NSDictionary elements, you can do this:
NSMutableArray *array = [[NSMutableArray alloc] initiWithArray:dic[#"number1"]];
or
NSMutableArray *array = [NSMutableArray arrayWithArray:dic[#"number1"]];
To add object into NsDictionary Array do:
NSMutableDictionary * datos = [array objectAtIndex:i];
[datos setObject:#"hola" objectForKey#"newKey"];
I have a small doubt that is I have an NSArray which contains the following 4 objects:
Genesis, 1 Kings, leviticus, 2 Kings
I want to sort this array in dictionary order like i want an expected output like this
1 Kings, 2 Kings, Genesis, leviticus
How can this be achieved?
Go to this link:
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Collections/Articles/Arrays.html#//apple_ref/doc/uid/20000132-SW5
This is Apple documentation and your problem is solved over there.
Check out the example.
//First create the array of dictionaries
NSString *last = #"lastName";
NSString *first = #"firstName";
NSMutableArray *array = [NSMutableArray array];
NSArray *sortedArray;
NSDictionary *dict;
dict = [NSDictionary dictionaryWithObjectsAndKeys:
#"Jo", first, #"Smith", last, nil];
[array addObject:dict];
dict = [NSDictionary dictionaryWithObjectsAndKeys:
#"Joe", first, #"Smith", last, nil];
[array addObject:dict];
dict = [NSDictionary dictionaryWithObjectsAndKeys:
#"Joe", first, #"Smythe", last, nil];
[array addObject:dict];
dict = [NSDictionary dictionaryWithObjectsAndKeys:
#"Joanne", first, #"Smith", last, nil];
[array addObject:dict];
dict = [NSDictionary dictionaryWithObjectsAndKeys:
#"Robert", first, #"Jones", last, nil];
[array addObject:dict];
//Next we sort the contents of the array by last name then first name
// The results are likely to be shown to a user
// Note the use of the localizedCaseInsensitiveCompare: selector
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];
sortedArray = [array sortedArrayUsingDescriptors:descriptors];
This code is an example from Apple documentation.
You can sort an array of NSString alphabetically like this:
NSArray *sortedArray = [myArray sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
Aim: To obtain an NSArray containing unique keys for given NSDictionary(s) using elegant code
Example Code with Current Working Solution:
NSArray *data = [[NSArray alloc] initWithObjects:
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:1], #"a", [NSNumber numberWithInt:2], #"b", nil],
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:3], #"b", [NSNumber numberWithInt:4], #"c", nil],
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:5], #"a", [NSNumber numberWithInt:6], #"c", nil],
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:7], #"b", [NSNumber numberWithInt:8], #"a", nil],
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:8], #"c", [NSNumber numberWithInt:9], #"b", nil],
nil];
// create an NSArray of all the dictionary keys within the NSArray *data
NSMutableSet *setKeys = [[NSMutableSet alloc] init];
for (int i=0; i<[data count]; i++) {
[setKeys addObjectsFromArray:[[data objectAtIndex:i] allKeys]];
}
NSArray *arrayKeys = [setKeys allObjects];
NSLog(#"arrayKeys: %#", arrayKeys);
Which returns the desired array of keys:
2012-06-11 16:52:57.351 test.kvc[6497:403] arrayKeys: (
a,
b,
c
)
Question: Is there a more elegant way of approaching this? Surely there must be some KVC approach that can get all the keys without having to iterate through the array? I've been looking at Apple Developer Documentation and can't see a solution. Any ideas? (looking at purely elegance of code rather than performance).
Normally you could use KVC by doing something like this:
NSArray *uniqueKeys = [data valueForKeyPath:#"#distinctUnionOfArrays.allKeys";
However NSDictionary overrides the valueForKey: selector which is used by the KVC internals, so this will not work correctly.
The documentation for NSDictionary's valueForKey: method tells us that:
If key does not start with “#”, invokes objectForKey:. If key does start with “#”, strips the “#” and invokes [super valueForKey:] with the rest of the key.
So we just insert an # before allKeys:
NSArray *uniqueKeys = [data valueForKeyPath:#"#distinctUnionOfArrays.#allKeys"];
And we get what we want:
(lldb) po [data valueForKeyPath:#"#distinctUnionOfArrays.#allKeys"]
(id) $14 = 0x07bb2fc0 <__NSArrayI 0x7bb2fc0>(
c,
a,
b
)
This is less ugly, and possibly marginally faster, I suppose:
NSMutableSet *setKeys = [[NSMutableSet alloc] init];
for (NSDictionary* dict in data) {
for (id key in [dict keyEnumerator]) {
[setKeys addObject:key];
}
}
But you're not doing a particularly common operation, so I wouldn't expect to find some incredibly elegant method. If that's what you want, go learn Haskell.
You could try this:
NSMutableSet *setKeys = [[NSMutableSet alloc] init];
for(NSDictionary *dict in data) {
[setKeys addObjectsFromArray:[dict allKeys]];
}
NSArray *arrayKeys = [setKeys allObjects];
If you prefer blocks you could use this:
[data enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[setKeys addObjectsFromArray:[obj allKeys]];
}];
What is the difference between of Parsing in the following code segments.
which codes segments is faster in Parsing?
NSArray *arr = [[NSArray alloc] initWithObjects:#"Apple",#"Macbook", nil];
NSMutableArray *data = (NSMutableArray *)arr;
(and)
NSArray *arr = [[NSArray alloc] initWithObjects:#"Apple",#"Macbook", nil];
NSMutableArray *data = [NSMutableArray arrayWithArray:arr];
You have the same mistake in both snippets, you allocate memory for the object, and then assign something else to data, which makes you lose the previous (and have memory leak), e.g. this:
NSMutableArray *data = [[NSMutableArray alloc] init];
data = [NSMutableArray arrayWithArray:arr];
should be
NSMutableArray *data = [NSMutableArray arrayWithArray:arr];
Now for the question itself:
The first case is a bad idea, you cast the NSArray, but you canot modify it, as you didn't really changed its type, only assigned it to NSMutaleArray pointer.
The second case will create a new NSMutableArray which is mutable, with the contents of the NSArray, and this is cool, you may alter this array now.
It looks like what you want is either:
NSArray *arr = [[NSArray alloc] initWithObjects:#"Apple",#"Macbook", nil];
NSMutableArray *data = [arr mutableCopy];
or:
NSMutableArray *data = [[NSMutableArray alloc] initWithObjects:#"Apple",#"Macbook", nil];