Given is the following array (each block [] represents an entry):
[A=1] [A=5] [S=3] [A=7] [C=3] [T=2] [F=9] [Z=4] [N] [C=3] [E=8]
[A=7] [N] [Z=6] [Q=1] [P=2] [Y=7] [S=3] [N]
I need to split it in to objects of type 'N' (NObject) where as every other character represents a specific property of that NObject object until the next occurence of 'N'. Until the first occurrence of 'N', the characters belong to another object (let's call it the PObject). So the tasks should fulfill the follwing:
Currently, in pseudocode my solution looks like the following which I find is far from ideal.
PObject pobject = new PObject();
NObject nobject;
CollectionOfKeyValuePairs collection = MyArray.Split('=').MapKeysValues()
foreach(entry in collection) {
switch(entry.Key):
case A:
(nobject ?? (CommonBase) pobject).A += entry.Value; break;
case B:
(nobject ?? (CommonBase) pobject).B += entry.Value; break;
case C:
(nobject ?? (CommonBase) pobject).C += entry.Value; break;
case E:
pobject.E += entry.Value; break;
case F:
(nobject ?? (CommonBase) pobject).F += entry.Value; break;
case G:
(nobject ?? (CommonBase) pobject).G += entry.Value; break;
case H:
(nobject ?? (CommonBase) pobject).H += entry.Value; break;
...
...
...
case N:
nobject = new NObject();
....
....
}
}
Which gives me exactly what I want:
[pobject]
A = 23
B = 63
C = 23
...
[nobject]
A = 34
B = 82
C = 12
...
[nobject]
H = 236
K = 2
...
[nobject]
// N occurred in array, but no properties followed
But with over 30 possible property identifiers (which means 30 switch conditions) and a property assigned only based on the fact that nobject may be null (and creating a new one each 'N' char occurrence): The code is incredibly smelly. But I don't know how to do it different, maybe with builtin collection functions, LINQ or anything other.
You could use Dictionary to store key-value pairs instead of explicitly create properties for each possible case. Something like:
List<Dictionary<char,int>> listOfPNObjects = new List<Dictionary<char,int>>();
listOfPNObjects.Add(new Dictionary<char,int>()) //create default P dictionary
foreach(entry in collection) {
if(entry.Key == N)
{
listOfPNObjects.Add(new Dictionary<char,int>());
}
else
{
listOfPNObjects[listOfPNObjects.Count - 1].Add(entry.key, entry.value);
}
}
I've rewritten your code by using reflection and LINQ:
var objects = keyValuePairList
.Aggregate<KeyValuePair<string, dynamic>, List<CommonBase>>(
new List<CommonBase>(), (a, p) =>
{
CommonBase cObject;
if (p.Key == "N")
{
cObject = new NObject();
a.Add(cObject);
}
if (a.Count == 0)
{
cObject = new PObject();
Process(p, ref cObject);
a.Add(cObject);
}
else
{
cObject = a.Last();
Process(p, ref cObject);
}
return a;
});
Inside the Process
method is where you may handle the processing of the properties, based on their type:
private static void Process(
KeyValuePair<string, dynamic> kvPair,
ref CommonBase cObject)
{
var propertyInfo = typeof(CommonBase).GetProperty(kvPair.Key);
switch (propertyInfo.PropertyType.FullName)
{
case "System.Int32":
propertyInfo
.SetValue(cObject,
(int)propertyInfo.GetValue(cObject) + (int)kvPair.Value);
break;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With