I have two lists, each containing two objects of a class called TestData
TestData td1_a = new TestData("td1", "val11_a", null, "val13_a");
TestData td1_b = new TestData("td1", "val11_b", "val12_b", null);
TestData td2_a = new TestData("td2", "val21_a", "val22_a", null);
TestData td2_b = new TestData("td2", "val21_b", null, "val23_b");
List<TestData> list_a = new List<TestData>() {td1_a, td2_a};
List<TestData> list_b = new List<TestData>() {td1_b, td2_b};
TestData
is defined as
public class TestData {
public string DataName;
public string Value1;
public string Value2;
public string Value3;
public TestData(string name, string val1, string val2, string val3) {
DataName = name;
Value1 = val1;
Value2 = val2;
Value3 = val3;
}
}
Note that the two lists each contain two TestData
objects whose DataName
values are "td1"
and "td2"
How to merge the two lists such that the final result would be a single list whose members are two TestData
objects where the objects with the same DataName
merged and the value of the later override the value of the earlier if it is not null
in a clean way?
So if I do mergeList(list_a, list_b)
, the result would be a list with members of:
TestData td1_merged = new TestData("td1", "val11_b", "val12_b", "val13_a");
TestData td2_merged = new TestData("td2", "val21_b", "val22_a", "val22_b");
That is, _b
is replacing _a
whenever possible
and if I reverse the order mergeList(list_b, list_a)
, the result would be a list having member of:
TestData td1_merged = new TestData("td1", "val11_a", "val12_b", "val13_a");
TestData td2_merged = new TestData("td2", "val21_a", "val22_a", "val22_b");
Where _a
is replacing _b
instead.
At this moment, this is the best I can do with LINQ aggregate:
private List<TestData> mergeList(List<TestData> list_1, List<TestData> list_2) {
return list_1.Concat(list_2) //combining list_1 and list_2 depends on the given sequence
.GroupBy(td => td.DataName) //making groups based on DataName
.Select(g => g.Aggregate(g.First(), (a, b) => { //merge the values of the elements
if (b.Value1 != null) //tedious way of giving the conditions!
a.Value1 = b.Value1;
if (b.Value2 != null)
a.Value2 = b.Value2;
if (b.Value3 != null)
a.Value3 = b.Value3;
return a;
})).ToList();
}
It works fine except for the fact that to make conditions for overriding when not null, I have to write it once for each object. Is there a cleaner way to do it?
Edited:
I do this because I encounter a problem where an object can be partially defined by separated developers on different files. My job is to create, but not to duplicate, the objects created in a smart way such that if the object is defined in more than one file, the later file additional definition will override the early ones, but not overriding everything (what has been defined in the earlier file remains whenever there is no update).
Example, if in one of the file, it is defined:
Chip_ResetSource.bits =[hw_pin=0, power_on=1, missing_clock=2, watchdog=3, software_force=4, comparator=5, convert_start_0=6].
And elsewhere, it is also defined:
Chip_ResetSource =type=uint8;policy=read;
And somewhere else,
Chip_ResetSource =address=2500;unit=count;formula=1;max=255;min=0;
Then I just need to combine all of them. But if in another (later) file there is additional info about Chip_ResetSource:
Chip_ResetSource =address=2501;
Then, while all other info of Chip_ResetSource must remain the same after the third info Chip_ResetSource =address=2500;unit=count;formula=1;max=255;min=0;, its address property must be changed from 2500 to 2501 due to the fourth info.
So, given that problem, I think if I can just create one method to read all the given property at the instantiation and then another method to cleanly merge when other file is read, that will be great!