using System;
using System.Collections.Generic;
using System.Linq;
public class Test
{
public string Property1;
public string Property2;
public string Property3;
public string Property4;
public int Property5;
public int Property6;
public int Property7;
public int Property8;
}
public class Program
{
public static void Main()
{
List<Test> testList = new List<Test>();
testList.Add(new Test { Property1 = "A", Property2 = "B", Property3 = "C", Property4 = "D", Property5 = 1, Property6 = 2, Property7 = 3, Property8 = 4, });
testList.Add(new Test { Property1 = "AA", Property2 = "BB", Property3 = "CC", Property4 = "DD", Property5 = 7, Property6 = 8, Property7 = 9, Property8 = 10, });
testList.Add(new Test { Property1 = "A", Property2 = "B", Property3 = "C", Property4 = "Z", Property5 = 10, Property6 = 20, Property7 = 30, Property8 = 40, });
Console.WriteLine("Input:");
Print(testList);
// string, string, string = Property1, Property2, Property3
var dict = new Dictionary<Tuple<string, string, string>, List<Test>>();
foreach (var el in testList)
{
List<Test> list;
var key = Tuple.Create(el.Property1, el.Property2, el.Property3);
if (!dict.TryGetValue(key, out list))
{
list = new List<Test>();
dict.Add(key, list);
}
list.Add(el);
}
var output = new List<Test>(dict.Count);
foreach (var kv in dict)
{
var list = kv.Value;
var el = new Test
{
Property1 = kv.Key.Item1,
Property2 = kv.Key.Item2,
Property3 = kv.Key.Item3,
Property4 = list[0].Property4,
};
output.Add(el);
for (int i = 0; i < list.Count; i++)
{
el.Property5 += list[i].Property5;
el.Property6 += list[i].Property6;
el.Property7 += list[i].Property7;
el.Property8 += list[i].Property8;
}
}
Console.WriteLine();
Console.WriteLine("Output:");
Print(output);
}
public static void Print(IEnumerable<Test> els)
{
foreach (var el in els)
{
Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}", el.Property1, el.Property2, el.Property3, el.Property4, el.Property5, el.Property6, el.Property7, el.Property8);
}
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYzsKdXNpbmcgU3lzdGVtLkxpbnE7CgpwdWJsaWMgY2xhc3MgVGVzdAp7CiAgICBwdWJsaWMgc3RyaW5nIFByb3BlcnR5MTsKICAgIHB1YmxpYyBzdHJpbmcgUHJvcGVydHkyOwogICAgcHVibGljIHN0cmluZyBQcm9wZXJ0eTM7CiAgICBwdWJsaWMgc3RyaW5nIFByb3BlcnR5NDsKICAgIHB1YmxpYyBpbnQgUHJvcGVydHk1OwogICAgcHVibGljIGludCBQcm9wZXJ0eTY7CiAgICBwdWJsaWMgaW50IFByb3BlcnR5NzsKICAgIHB1YmxpYyBpbnQgUHJvcGVydHk4Owp9CgpwdWJsaWMgY2xhc3MgUHJvZ3JhbQp7CglwdWJsaWMgc3RhdGljIHZvaWQgTWFpbigpCgl7CiAgICAgICAgTGlzdDxUZXN0PiB0ZXN0TGlzdCA9IG5ldyBMaXN0PFRlc3Q+KCk7CgogICAgICAgIHRlc3RMaXN0LkFkZChuZXcgVGVzdCB7IFByb3BlcnR5MSA9ICJBIiwgUHJvcGVydHkyID0gIkIiLCBQcm9wZXJ0eTMgPSAiQyIsIFByb3BlcnR5NCA9ICJEIiwgUHJvcGVydHk1ID0gMSwgUHJvcGVydHk2ID0gMiwgUHJvcGVydHk3ID0gMywgUHJvcGVydHk4ID0gNCwgfSk7CiAgICAgICAgdGVzdExpc3QuQWRkKG5ldyBUZXN0IHsgUHJvcGVydHkxID0gIkFBIiwgUHJvcGVydHkyID0gIkJCIiwgUHJvcGVydHkzID0gIkNDIiwgUHJvcGVydHk0ID0gIkREIiwgUHJvcGVydHk1ID0gNywgUHJvcGVydHk2ID0gOCwgUHJvcGVydHk3ID0gOSwgUHJvcGVydHk4ID0gMTAsIH0pOwogICAgICAgIHRlc3RMaXN0LkFkZChuZXcgVGVzdCB7IFByb3BlcnR5MSA9ICJBIiwgUHJvcGVydHkyID0gIkIiLCBQcm9wZXJ0eTMgPSAiQyIsIFByb3BlcnR5NCA9ICJaIiwgUHJvcGVydHk1ID0gMTAsIFByb3BlcnR5NiA9IDIwLCBQcm9wZXJ0eTcgPSAzMCwgUHJvcGVydHk4ID0gNDAsIH0pOwoKICAgICAgICBDb25zb2xlLldyaXRlTGluZSgiSW5wdXQ6Iik7CiAgICAgICAgUHJpbnQodGVzdExpc3QpOwoKICAgICAgICAvLyBzdHJpbmcsIHN0cmluZywgc3RyaW5nID0gUHJvcGVydHkxLCBQcm9wZXJ0eTIsIFByb3BlcnR5MwogICAgICAgIHZhciBkaWN0ID0gbmV3IERpY3Rpb25hcnk8VHVwbGU8c3RyaW5nLCBzdHJpbmcsIHN0cmluZz4sIExpc3Q8VGVzdD4+KCk7CgogICAgICAgIGZvcmVhY2ggKHZhciBlbCBpbiB0ZXN0TGlzdCkKICAgICAgICB7CiAgICAgICAgICAgIExpc3Q8VGVzdD4gbGlzdDsKCiAgICAgICAgICAgIHZhciBrZXkgPSBUdXBsZS5DcmVhdGUoZWwuUHJvcGVydHkxLCBlbC5Qcm9wZXJ0eTIsIGVsLlByb3BlcnR5Myk7CgogICAgICAgICAgICBpZiAoIWRpY3QuVHJ5R2V0VmFsdWUoa2V5LCBvdXQgbGlzdCkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGxpc3QgPSBuZXcgTGlzdDxUZXN0PigpOwogICAgICAgICAgICAgICAgZGljdC5BZGQoa2V5LCBsaXN0KTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGlzdC5BZGQoZWwpOwogICAgICAgIH0KCiAgICAgICAgdmFyIG91dHB1dCA9IG5ldyBMaXN0PFRlc3Q+KGRpY3QuQ291bnQpOwoKICAgICAgICBmb3JlYWNoICh2YXIga3YgaW4gZGljdCkKICAgICAgICB7CiAgICAgICAgICAgIHZhciBsaXN0ID0ga3YuVmFsdWU7CgogICAgICAgICAgICB2YXIgZWwgPSBuZXcgVGVzdAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBQcm9wZXJ0eTEgPSBrdi5LZXkuSXRlbTEsCiAgICAgICAgICAgICAgICBQcm9wZXJ0eTIgPSBrdi5LZXkuSXRlbTIsCiAgICAgICAgICAgICAgICBQcm9wZXJ0eTMgPSBrdi5LZXkuSXRlbTMsCiAgICAgICAgICAgICAgICBQcm9wZXJ0eTQgPSBsaXN0WzBdLlByb3BlcnR5NCwKICAgICAgICAgICAgfTsKCiAgICAgICAgICAgIG91dHB1dC5BZGQoZWwpOwoKICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBsaXN0LkNvdW50OyBpKyspCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGVsLlByb3BlcnR5NSArPSBsaXN0W2ldLlByb3BlcnR5NTsKICAgICAgICAgICAgICAgIGVsLlByb3BlcnR5NiArPSBsaXN0W2ldLlByb3BlcnR5NjsKICAgICAgICAgICAgICAgIGVsLlByb3BlcnR5NyArPSBsaXN0W2ldLlByb3BlcnR5NzsKICAgICAgICAgICAgICAgIGVsLlByb3BlcnR5OCArPSBsaXN0W2ldLlByb3BlcnR5ODsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgQ29uc29sZS5Xcml0ZUxpbmUoKTsKICAgICAgICBDb25zb2xlLldyaXRlTGluZSgiT3V0cHV0OiIpOwogICAgICAgIFByaW50KG91dHB1dCk7Cgl9CgkKCXB1YmxpYyBzdGF0aWMgdm9pZCBQcmludChJRW51bWVyYWJsZTxUZXN0PiBlbHMpCgl7CiAgICAgICAgZm9yZWFjaCAodmFyIGVsIGluIGVscykKICAgICAgICB7CiAgICAgICAgICAgIENvbnNvbGUuV3JpdGVMaW5lKCJ7MH0gezF9IHsyfSB7M30gezR9IHs1fSB7Nn0gezd9IiwgZWwuUHJvcGVydHkxLCBlbC5Qcm9wZXJ0eTIsIGVsLlByb3BlcnR5MywgZWwuUHJvcGVydHk0LCBlbC5Qcm9wZXJ0eTUsIGVsLlByb3BlcnR5NiwgZWwuUHJvcGVydHk3LCBlbC5Qcm9wZXJ0eTgpOwogICAgICAgIH0KCX0KfQ==