How to remove array / structure list items that have 2 common items

The presence of a list of structures or, possibly, a list of arrays, each of which contains 3 elements, for example

12 8 7 5 1 0 7 3 2 10 6 5 6 2 1 8 4 3 6 1 5 7 2 6 8 3 7 9 4 8 11 7 6 13 9 8 11 6 10 12 7 11 13 8 12 14 9 13 

I want to get rid of elements that have 2 common elements in the list, in the example I would like to remove

 5 1 0 6 2 1 6 1 5 7 3 2 7 2 6 8 4 3 8 3 7 has 2 same items as row 7,3,2 9 4 8 has 2 same items as row 8,4,3 10 6 5 11 7 6 11 6 10 has 2 same items as row 11,7,6 12 7 11 has 2 same items as row 11,7,10 12 8 7 13 8 12 13 9 8 14 9 13 has 2 same items as row 13,9,8 

Therefore, using the structs approach, I think that sorting the list by element A, and then looping and comparing the elements, so if the current element has 2 values ​​equal to another element in the list, I do not add it to the list of results, however I am stuck and don't know if there is a better approach

 struct S { public int A; public int B; public int C; } public void test() { List<S> DataItems = new List<S>(); DataItems.Add(new S { A = 1, B = 2, C=3} ); DataItems.Add(new S { A = 12, B = 8, C = 7 }); DataItems.Add(new S { A = 5, B = 1, C = 0 }); DataItems.Add(new S { A = 7, B = 3, C = 2 }); DataItems.Add(new S { A = 10, B = 6, C = 5 }); DataItems.Add(new S { A = 6, B = 2, C = 1 }); DataItems.Add(new S { A = 8, B = 4, C = 3 }); DataItems.Add(new S { A = 6, B = 1, C = 5 }); DataItems.Add(new S { A = 7, B = 2, C = 6 }); DataItems.Add(new S { A = 8, B = 3, C = 7 }); DataItems.Add(new S { A = 9, B = 4, C = 8 }); DataItems.Add(new S { A = 11, B = 7, C = 6 }); DataItems.Add(new S { A = 13, B = 9, C = 8 }); DataItems.Add(new S { A = 11, B = 6, C = 10 }); DataItems.Add(new S { A = 12, B = 7, C = 11 }); DataItems.Add(new S { A = 13, B = 8, C = 12 }); DataItems.Add(new S { A = 14, B = 9, C = 13 }); var sortedList = DataItems.OrderBy(x => xA); List<S> resultList = new List<S>(); for (int i = 0; i < sortedList.Count (); i++) { for (int j = i+1; j < sortedList.Count(); j++) { if (sortedList.ElementAt(i).A == sortedList.ElementAt(j).A || sortedList.ElementAt(i).A == sortedList.ElementAt(j).B || sortedList.ElementAt(i).A == sortedList.ElementAt(j).C) { //ONE HIT, WAIT OTHER } } } } 

Is there a more efficient way to get a list without having an element with two identical elements, so I would get a solution instead of hardcoding?

 5 1 0 6 2 1 6 1 5 7 3 2 7 2 6 8 4 3 10 6 5 11 7 6 12 8 7 13 8 12 13 9 8 
+5
source share
2 answers

One way to solve it is to introduce intermediate methods in struct S :

 public struct S { public int A; public int B; public int C; public bool IsSimilarTo(S s) { int similarity = HasElement(A, s) ? 1 : 0; similarity += HasElement(B, s) ? 1 : 0; return similarity >= 2 ? true : HasElement(C, s); } public bool HasElement(int val, S s) { return val == sA || val == sB || val == sC; } public int HasSimilarInList(List<S> list, int index) { if (index == 0) return -1; for (int i = 0; i < index; ++i)//compare with the previous items if (IsSimilarTo(list[i])) return i; return -1; } } 

Then you can solve it like this without ordering:

 public void test() { List<S> DataItems = new List<S>(); DataItems.Add(new S { A = 1, B = 2, C = 3 }); DataItems.Add(new S { A = 12, B = 8, C = 7 }); DataItems.Add(new S { A = 5, B = 1, C = 0 }); DataItems.Add(new S { A = 7, B = 3, C = 2 }); DataItems.Add(new S { A = 10, B = 6, C = 5 }); DataItems.Add(new S { A = 6, B = 2, C = 1 }); DataItems.Add(new S { A = 8, B = 4, C = 3 }); DataItems.Add(new S { A = 6, B = 1, C = 5 }); DataItems.Add(new S { A = 7, B = 2, C = 6 }); DataItems.Add(new S { A = 8, B = 3, C = 7 }); DataItems.Add(new S { A = 9, B = 4, C = 8 }); DataItems.Add(new S { A = 11, B = 7, C = 6 }); DataItems.Add(new S { A = 13, B = 9, C = 8 }); DataItems.Add(new S { A = 11, B = 6, C = 10 }); DataItems.Add(new S { A = 12, B = 7, C = 11 }); DataItems.Add(new S { A = 13, B = 8, C = 12 }); DataItems.Add(new S { A = 14, B = 9, C = 13 }); int index = 1; //0-th element does not need to be checked while (index < DataItems.Count) { int isSimilarTo = DataItems[index].HasSimilarInList(DataItems, index); if (isSimilarTo == -1) { ++index; continue; } DataItems.RemoveAt(index); } } 
+5
source

Given an element ...

 { A = 1, B = 2, C = 3 } 

You have 3 possible combinations that can be repeated in another element, for example

 AB, AC & BC which is {1, 2}, {1, 3} & {2, 3} 

So, what would I do is iterate over your list, add these combinations to a char delimited dictionary (first the lowest number, so if B <A then adds BA, not AB). Thus, dictionary keys can be ...

 "1-2", "1-3", "2-3" 

Now, when you add each element, check if the key exists, if it does, you can ignore this element (do not add it to the list of results).

In terms of performance, it will be once through the entire list and using the dictionary to check items with two common numbers.

+8
source

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


All Articles