Hello I have a List<Tuple<int, int>>
and I want to check if there are repeated elements no matter the order. So, for example, if my list contains
List<Tuple<int, int>> tuple = new List<Tuple<int, int>>()
{
new Tuple<int, int>(1, 2),
new Tuple<int, int>(2, 1),
new Tuple<int, int>(3, 2)
};
I want to remove the the second item because it contains the same elements that the first but in reverse order (1,2) and (2,1).
What would be the most efficient way to do it?
CodePudding user response:
var set = new HashSet<long>();
var unique = tuple.Where(t => set.Add((long)Math.Max(t.Item1, t.Item2) << 32 | Math.Min(t.Item1, t.Item2)))
If you are not iterating once then add .ToList()
at the end
update
to remove from the original list
var set = new HashSet<long>();
for (int i = tuple.Count -1; i >= 0; i--)
{
if (!set.Add((long)Math.Max(t.Item1, t.Item2) << 32 | Math.Min(t.Item1, t.Item2)))
set.RemoveAt(i);
}
CodePudding user response:
You can use DistinctBy
function:
var withoutDuplicates = tuple
.DistinctBy(t => Tuple.Create(Math.Min(t.Item1, t.Item2), Math.Max(t.Item1, t.Item2)))
.ToList();
CodePudding user response:
You can define an IEqualityComparer
and then you can use Linq's Distinct
functionality:
var withoutDuplicate = tuple.Distinct(new IntegerTupleComparer()).ToList();
And here is a naive implementaion of the IEqualityComparer<Tuple<int, int>>
public class IntegerTupleComparer: IEqualityComparer<Tuple<int, int>>
{
public bool Equals(Tuple<int, int> lhs, Tuple<int, int> rhs)
{
if (lhs == null && rhs == null)
return true;
if (lhs == null || rhs == null)
return false;
return GetHashCode(rhs).Equals(GetHashCode(lhs));
}
public int GetHashCode(Tuple<int, int> _)
=> _.Item1.GetHashCode() _.Item2.GetHashCode();
}