Create combo boxes from multiple lists

I can’t figure it out, trying to figure it out, but I will explain as follows,

var combinedCoords = new List<List<int>>(); var coords = new List<List<int>> { new List<int>() {0, 1}, new List<int>() {0, 1, 2}, new List<int>() {1, 3, 4, 5}, new List<int>() {3, 4}, new List<int>() {7, 8}, new List<int>() {7, 8, 9}, new List<int>() {8, 9, 10} }; 

Here I have a coords variable that contains several List<int> ; I need some new lists to be filled in combinedCoords , which will contain several combined lists that have common numbers. From this should be compiled 2 combined lists, the first will be {0,1,2,3,4,5} , and the second will be {7,8,9,10} . To further illustrate what I am trying to say, below is a graphical representation where each circle is a list; a red number in brackets indicates the index of each list.

how it should look
(source: aboutireland.ie )

+6
source share
2 answers

It looks like you are looking for a list of connected components . I answered a similar question about this here , but this question is quite different, and I think it guarantees his own answer:

 var combinedCoords = new List<List<int>>(); foreach(var c in coords) { var merge = new List<List<int>>(); foreach(var g in combinedCoords) { if (c.Any(g.Contains)) { merge.Add(g); } } if (merge.Count == 0) { combinedCoords.Add(c); } merge.Add(c); for(int i = 1; i < merge.Count; i ++) { foreach(var v in merge[i].Except(merge[0])) { merge[0].Add(v); } combinedCoords.Remove(merge[i]); } } 

This creates two lists:

 { 0, 1, 2, 3, 4, 5 } { 7, 8, 9, 10 } 

If you reorganize coords and combinedCoords as List<HashSet<int>> , the algorithm is a bit simpler and should work better:

 var combinedCoords = new List<HashSet<int>>(); foreach(var c in coords) { var merge = new List<HashSet<int>>(combinedCoords.Where(c.Overlaps)); if (merge.Count == 0) { combinedCoords.Add(c); } else { merge[0].UnionWith(c); for(int i = 1; i < merge.Count; i ++) { merge[0].UnionWith(merge[i]); combinedCoords.Remove(merge[i]); } } } 
+4
source

Something like this should be completed with the help of coords containing only "related" values, based on what, in my opinion, is your requirement that any two lists with common values ​​should be combined into one list:

  bool combinedAny; do { combinedAny = false; for (int i = 0; i < coords.Count; i++) { for (int j = 0; j < i; j++) { if (coords[i].Intersect(coords[j]).Any()) { coords[j] = coords[i].Union(coords[j]).ToList(); coords.RemoveAt(i); combinedAny = true; break; } } if (combinedAny) { break; } } } while (combinedAny); 
+1
source

All Articles