6

I have a List of List of Strings, and I need to use the AddRange() Function to add set of items to it, but never duplicate items.

I used the following code :

List<List<string>> eList = new List<List<string>>();
List<List<string>> mergedList = new List<List<string>>(); 

//
// some code here
//

mergedList.AddRange(eList.Where(x => !mergedList.Contains(x)).ToList());

However it does not work.

All Duplicated items are added, so how could I solve that?

AyaZoghby
  • 341
  • 3
  • 7
  • 16

2 Answers2

9

A)

If what you mean from duplicate is both lists contain the same elements int the same order, then

List<List<string>> eList = new List<List<string>>();
eList.Add(new List<string>() { "a", "b" });
eList.Add(new List<string>() { "a", "c" });
eList.Add(new List<string>() { "a", "b" });


var mergedList = eList.Distinct(new ListComparer()).ToList();

public class ListComparer : IEqualityComparer<List<string>>
{
    public bool Equals(List<string> x, List<string> y)
    {
        return x.SequenceEqual(y);
    }

    public int GetHashCode(List<string> obj)
    {
        return obj.Take(5).Aggregate(23,(sum,s)=> sum ^= s.GetHashCode());
    }
}

B)

If the order of elements in the list is not important, then

List<List<string>> eList = new List<List<string>>();
eList.Add(new List<string>() { "a", "b" }); <--
eList.Add(new List<string>() { "a", "c" });
eList.Add(new List<string>() { "b", "a" }); <--

var mergedList = eList.Select(x => new HashSet<string>(x))
                      .Distinct(HashSet<string>.CreateSetComparer()).ToList();
Nick N.
  • 12,902
  • 7
  • 57
  • 75
I4V
  • 34,891
  • 6
  • 67
  • 79
  • @SergeyS it is a random(small) number. to calculate the hash code, you don't need to iterate all over the list especially if the list is very long. – I4V Jan 12 '13 at 21:03
  • It depends, maybe sometimes it will work good, but for some lists and data structures, it will be not so good :) – SergeyS Jan 12 '13 at 21:09
  • @SergeyS you are talking with no ground. It would work even I had have wrote it as `return 0` (only with a bad performance). – I4V Jan 12 '13 at 21:13
  • I did not say 'it will not work'. I said 'it will be not so good'. And this was said with great ground of computer science ;) It is all about performance of course, no doubts. – SergeyS Jan 12 '13 at 21:16
  • If 2 lists have same first 5 items, but different 6th item, `GetHashCode` will not work. – Tilak Jan 12 '13 at 22:22
  • Code is [here](http://pastebin.com/pvSVskAv). Run and check.. 2 Lists with same first five items, but different 6 items. `GetHashCode` (written in answer) is returning same values (tested in linqpad). It should return different as 6th items are different. – Tilak Jan 12 '13 at 22:36
  • @Tilak Of course they are so. It seems you don't know how `GetHashCode` works. Two objects with the same hashocde doesn't mean they are equal. but two objects with different hashcodes are surely not equal. Test my `Distinct` functions. It works as expected. – I4V Jan 12 '13 at 22:40
  • @Tilak In my comparer,for performance reosons, I take the first 5 element and return a hashcode which says "they *may be* equal", not they are equal. The real comparison is made in `Equals` function – I4V Jan 12 '13 at 22:49
  • @I4V, `GetHashCode` and `Equals` go hand in hand.This is not the case with you example. >"Two objects with the same hashocde don't mean they are equal". That is true, GetHashCode need not return different value for different objects but that **should** happen rarely. Not that you should compare first 5 items, and say it worked as expected. Even if you will `return 1` from `GetHashCode` it will work due to different `Equals` – Tilak Jan 12 '13 at 22:50
  • I have never said comparer will not work. Only thing i have said is `GetHashCode` will not work for >5 elements. – Tilak Jan 12 '13 at 22:53
  • @Tilak It depends on *how you see it*. It does its work and it is not wrong. If you will be happy, just remove `Take` – I4V Jan 12 '13 at 22:54
  • 1
    @Tilak What's about **Take(5).Aggregate(23,..** ? Why 5 value ? Why 23 value ? Which is the sense about it ? – Kiquenet Nov 06 '14 at 09:43
  • @I4V Maybe useful add explain and more details about ***Take(5).Aggregate(23*** in your answer. – Kiquenet Nov 06 '14 at 09:45
2

Try following LINQ query

mergeList.AddRange( eList.Where (x => mergeList.Where ( y => y.Intersect(x)).Any()));
Tilak
  • 30,108
  • 19
  • 83
  • 131
  • 1
    Trying this approach..its not compiling. Seems to not be recognizing the "y.Intersect" part even though I reference System.Linq. – BeYourOwnGod Dec 18 '13 at 18:51
  • 2
    Not compiles **using System.Linq**, y.Intersect not recognize. _Cannot implicity convert type IEnumerable to bool_ – Kiquenet Nov 06 '14 at 09:41
  • -1; Does not compile. Intersect is not found no extension found. Do have using System.Linq, tried with IEnumerable and an IList and LIst – t.durden Sep 01 '21 at 13:33