Reputation: 117
I've done a lot of digging and I can't seem to find an answer to this particular problem; answers to similar problems, but nothing quite like this.
Essentially, what I'm trying to do is take two C# lists, both of which contain a range of C# Objects comprised of string-integer pairs, then merge them together, joining the values of similar Objects.
Let's say my Object Class looks like this;
public class Object
{
public string Name;
public int Value;
}
And we'll also say that my lists look like this;
objectList1 objectList2
Name Value Name Value
Object1 1 Object1 1
Object2 1 Object2 1
Object3 1
Object4 1
Object5 1
My goal here is to combine the contents of objectList2
's Objects to the corresponding Objects in objectList1
. In this example, that would mean that objectList1
would look like this when all is said and done;
Name Value
Object1 2
Object2 2
Object3 1
Object4 1
Object5 1
Now I know this is possible to do with foreach
and FindIndex()
calls, but I'm almost positive there's a more efficient way to go about this. If I'm wrong, that's fine, but I'd like to know if I can optimize this because my gut tells me there has to be a simpler way.
Upvotes: 3
Views: 4693
Reputation: 11480
I believe what you're looking to do:
var contents = sample.Concat(example).GroupBy(n => n.Name);
Basically it will create a grouping, but it will append the list together. Then group based on the name, which will provide a numeric indicator of how many of the same name exist. Basically, you end up with a IGrouping<Key, Value>
.
For instance:
var merge = new List<Content>();
var contents = sample.Concat(example).GroupBy(n => n.Name);
foreach(var item in contents)
merge.Add(new Content() { Name = item.Key, Value = item.Sum(value => value.Value) });
You could also, do it with all Linq if you wanted:
var contents = example.Concat(sample)
.GroupBy(n => n.Name)
.SelectMany(content =>
content.Select((item, i) => new { Name = content.Key, Value = content.Sum(v => v.Value) }).Distinct());
Upvotes: 3
Reputation: 61
You can use LINQ as below
var list1 = new List<Object>();
list1.Add(new Object { Name = "Object1", Value = 1 });
list1.Add(new Object { Name = "Object2", Value = 1 });
list1.Add(new Object { Name = "Object3", Value = 1 });
list1.Add(new Object { Name = "Object4", Value = 1 });
list1.Add(new Object { Name = "Object5", Value = 1 });
var list2 = new List<Object>();
list2.Add(new Object { Name = "Object1", Value = 1 });
list2.Add(new Object { Name = "Object2", Value = 1 });
var total = from item1 in list1
join item2 in list2
on item1.Name equals item2.Name into list3
from subset in list3.DefaultIfEmpty()
select new Object
{
Name = item1.Name,
Value = item1.Value + (subset == null ? 0 : subset.Value)
};
Upvotes: 1
Reputation: 794
Best bet I can think of is to use Dictionary, assuming all keys are unique
do a foreach on the smaller Dictionary (not shown below), checking for matching keys in the other, and then modifying if found or adding if not found (note this algorithm is destructive, make a copy to return if you want to preserve the originals)
void Merge (Dictionary<string, int> a, Dictionary<string, int> b)
{
foreach (string key in a.Keys)
{
if (b.ContainsKey(key))
{
b[key] = b[key] + a[key];
}
else
{
b.Add(key, a[key]);
}
}
}
Upvotes: 1