nff
nff

Reputation: 151

Remove duplicate lists inside a list of lists in C#

How do I remove duplicate inner lists from main list?

var list1 = new List<object>() { 1,2,3 };
var list2 = new List<object>() { 4,5,6 };
var list3 = new List<object>() { 1,2,3 };

List<List<object>> mainList = new List<List<object>>() {list1, list2, list3};

I want to remove the list3 from the mainList so that no duplicates in the mainList.

Upvotes: 3

Views: 2965

Answers (2)

Hamzeh.Ebrahimi
Hamzeh.Ebrahimi

Reputation: 305

try following linq uery

var list1 = new List<object>() { 1, 2, 3 };
var list2 = new List<object>() { 4, 5, 6 };
var list3 = new List<object>() { 3, 1, 2 };

List<List<object>> mainList = new List<List<object>>() { list1, list2, list3 };

var distinctlist = mainList.Select(o => 
    { 
        var t = o.OrderBy(x=>x).Select(i => i.ToString()); 
        return new { Key= string.Join("", t),List=o }; 
    })
    .GroupBy(o => o.Key)
    .Select(o => o.FirstOrDefault())
    .Select(o => o.List);

Upvotes: 0

M.kazem Akhgary
M.kazem Akhgary

Reputation: 19169

Update: as mentioned in comments, order of items does not matter so {3,2,1} and {1,2,3} are considered duplicate.


There are a few concerns about your question. your inner list contains objects. if that means object can be anything and not just an int then you should make sure those objects override Equals and GetHashCode as well (or implement IEquatable<TSelf> where TSelf is the implementing type).

If your inner list just contains primitive types or common readonly structs such as DateTime or TimeSpan then you shouldn't worry.

You can use Distinct and EqualityComparer interface

var list1 = new List<object>() { 1, 2, 3 };
var list2 = new List<object>() { 4, 5, 6 };
var list3 = new List<object>() { 1, 2, 3 };

List<List<object>> mainList = new List<List<object>>() { list1, list2, list3 };

mainList = mainList.Distinct(ListEqualityComparer<object>.Default).ToList();

Equality comparer implementation.

public class ListEqualityComparer<T> : IEqualityComparer<List<T>>
{
    private readonly IEqualityComparer<T> _itemEqualityComparer;

    public ListEqualityComparer() : this(null) { }

    public ListEqualityComparer(IEqualityComparer<T> itemEqualityComparer)
    {
        _itemEqualityComparer = itemEqualityComparer ?? EqualityComparer<T>.Default;
    }

    public static readonly ListEqualityComparer<T> Default = new ListEqualityComparer<T>();

    public bool Equals(List<T> x, List<T> y)
    {
        if (ReferenceEquals(x, y)) return true;
        if (ReferenceEquals(x, null) || ReferenceEquals(y, null)) return false;
        return x.Count == y.Count && !x.Except(y, _itemEqualityComparer).Any();
    }

    public int GetHashCode(List<T> list)
    {
        int hash = 17;
        foreach (var itemHash in list.Select(x => _itemEqualityComparer.GetHashCode(x))
                                     .OrderBy(h => h))
        {
            hash += 31 * itemHash;
        }
        return hash;
    }
}

If your objects does not override Equals and GetHashCode you can make another equality comparer for your items as well and pass it to this equality comparer.

mainList = mainList.Distinct(new ListEqualityComparer<object>(myItemEqualityComparer)).ToList();

where myItemEqualityComparer is for comparing your objects

Upvotes: 6

Related Questions