FlySwat
FlySwat

Reputation: 175733

Checking for duplicates in a collection

Suppose you have a collection of Foo classes:

class Foo
{
    public string Bar;
    public string Baz;
}

List<Foo> foolist;

And you want to check this collection to see if another entry has a matching Bar.

bool isDuplicate = false;
foreach (Foo f in foolist)
{
     if (f.Bar == SomeBar)
     {
         isDuplicate = true;
         break;
     }
}

Contains() doesn't work because it compares the classes as whole.

Does anyone have a better way to do this that works for .NET 2.0?

Upvotes: 4

Views: 1449

Answers (9)

Majid Shahabfar
Majid Shahabfar

Reputation: 4839

Here are 4 ways to check if the collection has no duplicates:

public static bool LinqAll<T>(IEnumerable<T> enumerable)
{
    HashSet<T> set = new();

    return !enumerable.All(set.Add);
}

public static bool LinqAny<T>(IEnumerable<T> enumerable)
{
    HashSet<T> set = new();

    return enumerable.Any(element => !set.Add(element));
}

public static bool LinqDistinct<T>(IEnumerable<T> enumerable)
{
    return enumerable.Distinct().Count() != enumerable.Count();
}

public static bool ToHashSet<T>(IEnumerable<T> enumerable)
{
    return enumerable.ToHashSet().Count != enumerable.Count();
}

Upvotes: 0

fvoncina
fvoncina

Reputation:

If you can use LINQ you can do the following:

bool contains = foolist.Where(f => f.Bar == someBar).Count() != 0;

Upvotes: 0

Joel Coehoorn
Joel Coehoorn

Reputation: 416159

If the 'Bar's for your class are unique (a key to class Foo), then you can try implementing a System.Collections.ObjectModel.KeyedCollection. It's pretty simple: just implement the GetKeyForItem() method.

class Foo
{
    public string Bar;
    public string Baz;
}

class FooList : KeyedCollection<string, Foo>
{
    protected override string GetKeyForItem(Foo item)
    {
        return item.Bar;
    }
}

FooList fooList;

Upvotes: 0

Chris Marasti-Georg
Chris Marasti-Georg

Reputation: 34710

Implement the IEqualityComparer<T> interface, and use the matching Contains method.

public class MyFooComparer: IEqualityComparer<Foo> {

   public bool Equals(Foo foo1, Foo foo2) {
      return Equals(foo1.Bar, foo2.Bar);
   }

   public int GetHashCode(Foo foo) {
      return foo.Bar.GetHashCode();
   }
}

Foo exampleFoo = new Foo();
exampleFoo.Bar = "someBar";
if(myList.Contains(exampleFoo, new MyFooComparer())) {
    ...
}

Upvotes: 4

Austin Salonen
Austin Salonen

Reputation: 50245

If you override Equals on Foo to make key on Bar, Contains() will work.

Upvotes: 0

Karg
Karg

Reputation: 1527

fooList.Exists(item => item.Bar == SomeBar)

or with anonymous delegate

fooList.Exists(delegate(Foo item) {return item.Bar == SomeBar;})

Upvotes: 0

James Curran
James Curran

Reputation: 103605

fooList.Exists(item => item.Bar == SomeBar)

That's not LINQ, but a Lambda expression, but nevertheless, it uses a v3.5 feature. No problem:

fooList.Exists(delegate(Foo Item) { return item.Bar == SomeBar});

That should work in 2.0.

Upvotes: 10

readonly
readonly

Reputation: 356044

If you need the element, you can also use List.Find() and pass in a delegate that returns true for your definition of a "match" (http://msdn.microsoft.com/en-us/library/x0b5b5bc.aspx).

There's an example of how to define a delegate on that MSDN doc.

Upvotes: 0

ripper234
ripper234

Reputation: 230396

You probably want to use C5.HashSet, and implement Equals and GetHashCode() for Foo.

Upvotes: -1

Related Questions