C # Combining 3 collection lists into one list

I have 3 collection lists as shown below.

public static List<Thing> English = new List<Thing> { new Thing {ID = 1, Stuff = "one"}, new Thing {ID = 2, Stuff = "two"}, new Thing {ID = 3, Stuff = "three"} }; public static List<Thing> Spanish = new List<Thing> { new Thing {ID = 1, Stuff = "uno"}, new Thing {ID = 2, Stuff = "dos"}, new Thing {ID = 3, Stuff = "tres"}, new Thing {ID = 4, Stuff = "cuatro"} }; public static List<Thing> German = new List<Thing> { new Thing {ID = 1, Stuff = "eins"}, new Thing {ID = 2, Stuff = "zwei"}, new Thing {ID = 3, Stuff = "drei"} }; 

At runtime, the length of the list may vary. For example, German can take 5 meanings, English with 2 and Spanish with one.

I need to find which list has the maximum value, and I need to get the result in the following format.

  Id English German Spanish 1 one eins uno 2 two zwei dos 3 three drei tres 4 cuatro 

Could you help me solve this problem.

+4
source share
3 answers

Try the following:

 English.Select(t => new Tuple<Thing,int>(t, 1)).Concatenate( German.Select(t => new Tuple<Thing,int>(t, 2)).Concatenate( Spanish.Select(t => new Tuple<Thing,int>(t, 3)) ) ).GroupBy(p => p.Item1.ID) .Select(g => new { Id = g.Key , English = g.Where(t => t.Item2==1).Select(t => t.Item2.Stuff).SingleOrDefault() , German = g.Where(t => t.Item2==2).Select(t => t.Item2.Stuff).SingleOrDefault() , Spanish = g.Where(t => t.Item2==3).Select(t => t.Item2.Stuff).SingleOrDefault() }); 

The idea is to mark the source elements with your collection origin ( 1 for English, 2 for German, 3 for Spanish), group them by identifier, and then retrieve details for individual languages ​​using the tag that we added on the first step.

+6
source

If they all start with one and never miss any numbers (but can end at any point), you can use a simpler approach, for example:

 int count = Math.Max(English.Count, Math.Max(Spanish.Count, German.Count)); var query = Enumerable.Range(0, count) .Select(num => new { Id = num + 1, English = GetValue(English, num), Spanish = GetValue(Spanish, num), German = GetValue(German, num), }); 

If it is possible for numbers to be skipped or not starting with one, you could use this slightly more complex approach:

 var englishDic = English.ToDictionary(thing => thing.ID, thing => thing.Stuff); var spanishDic = Spanish.ToDictionary(thing => thing.ID, thing => thing.Stuff); var germanDic = German.ToDictionary(thing => thing.ID, thing => thing.Stuff); var query = englishDic.Keys .Union(spanishDic.Keys) .Union(germanDic.Keys) .Select(key => new { Id = key, English = GetValue(englishDic, key), Spanish = GetValue(spanishDic, key), German = GetValue(germanDic, key), }); 

To prevent erroneous argument errors, several auxiliary functions were required:

 public static string GetValue(Dictionary<int, string> dictionary, int key) { string output; if (dictionary.TryGetValue(key, out output)) return output; else return ""; } public static string GetValue(List<Thing> list, int index) { if (index < list.Count) return list[index].Stuff; else return ""; } 
+1
source

It was fun:)

I did this, which works, but, like many of these answers, is not very effective:

 public IEnumerable ListEmAll() { return new List<int>() // just for balance, start with empty list .Union( English.Select(o => o.ID) ) .Union( Spanish.Select(o => o.ID) ) .Union( German.Select(o => o.ID) ) .OrderBy(id => id) .Select(id => new { ID = id, English = English.Where(o => o.ID == id).Select(o => o.Stuff), Spanish = Spanish.Where(o => o.ID == id).Select(o => o.Stuff), German = German.Where(o => o.ID == id).Select(o => o.Stuff) }); } 

But I like better not to use Linq and return a complex dictionary ... there are no expensive searches on the lists.

 // keep a list of the languages for later static Dictionary<string, List<Thing>> languages = new Dictionary<string, List<Thing>>(){ {"English", English}, {"Spanish", Spanish}, {"German", German} }; // result[3]["English"] = "three" public Dictionary<int, Dictionary<string, string>> ListEmAll_better() { Dictionary<int, Dictionary<string, string>> result = new Dictionary<int, Dictionary<string, string>>(); foreach(var lang in languages.Keys) { foreach(var thing in languages[lang]) { if(!result.ContainsKey(thing.ID)) { result[thing.ID] = new Dictionary<string, string>(); } result[thing.ID][lang] = thing.Stuff; } } return result; } 
0
source

Source: https://habr.com/ru/post/1441333/


All Articles