tags:

views:

105

answers:

5

Here is the story:

Im trying to make a list of different clusters... I only want to have the necessary clusters... And Clusters can be the same.

How can I add this to a list by checking if the list contains the object (I know objects cant be passed here)

This is my sample quote:

foreach (Cluster cluster in clustersByProgramme)
{
    if (!clusterList.Contains(cluster))
    {
        clusterList.Add(cluster);
    }
}
+2  A: 

If you're using .NET 3.5, use a HashSet to do this.

HashSet<Cluster> clusterList = new HashSet<Cluster>();
foreach (Cluster cluster in clustersByProgramme)
{
     clusterList.Add(cluster);
}

In this case, also make sure that if cluster1 == cluster2, then

cluster1.Equals(cluster2);
cluster2.Equals(cluster1); //yeah, could be different depending on your impl
cluster1.GetHashCode() == cluster2.GetHashCode();
RichardOD
A `HashSet<T>` won't work - the OP's list _can_ contain duplicates, just not certain duplicates.
Andrew Hare
Yes it will work- he doesn't want to add duplicates.
RichardOD
Unless I'm misreading the requirements, which I don't think I am.
RichardOD
Yeah, re-reading the requirments it looks like he is creating a new, unqiue list. In that case a HashSet<T> would be best option, presuming no ordering is required.
Dan Diplo
+3  A: 

Your example is about as simple as it is going to get. The only thing I could possibly recommend is that you use the Exists method:

The Predicate is a delegate to a method that returns true if the object passed to it matches the conditions defined in the delegate. The elements of the current List are individually passed to the Predicate delegate, and processing is stopped when a match is found.

This method performs a linear search; therefore, this method is an O(n) operation, where n is Count.

Andrew Hare
+8  A: 

Your code should work; if it hasn't, you might be using different object instances that represent the same actual cluster, and you perhaps haven't provided a suitable Equals implementation (you should also update GetHashCode at the same time).

Also - in .NET 3.5, this could be simply:

var clusterList = clustersByProgramme.Distinct().ToList();


As an example of class that supports equality tests:

class Cluster // possibly also IEquatable<Cluster>
{
    public string Name { get { return name; } }
    private readonly string name;
    public Cluster(string name) { this.name = name ?? ""; }
    public override string ToString() { return Name; }
    public override int GetHashCode() { return Name.GetHashCode(); }
    public override bool Equals(object obj)
    {
        Cluster other = obj as Cluster;
        return obj == null ? false : this.Name == other.Name;
    }
}
Marc Gravell
+1. That's a good point about Equals/HashCode.
RichardOD
Bonus for making the name field readonly, that's the correct way to reimplement GetHashCode(), without the world blowing up ;)
Pop Catalin
@Pop- yeah immutable fields are the way to for GetHashCode().
RichardOD
Sorry - don't like the `name ?? ""` - throw an excpetion instead.
Eric Smith
@Eric- indeed, that is an option (`ArgumentNullException`). I'll be honest; in this example it was mainly to safe space...
Marc Gravell
@Marc, is it better to do the name and Name members like you did, or is it better to just have private readonly string Name; and use it everywhere instead?
Joan Venge
If the question is "should I still go via a property, or should I just use a field", then note that the JIT will almost certainly "inline" a basic "return field;" getter - so there is no significant difference. Except that accessing the property is more flexible if you change things later.
Marc Gravell
Thanks Marc. That's what I meant. The reason I asked is, I generally try to make things immutable and having a readonly Name field seems more clear to me. I wish ti was possible to have readonly automatic properties.
Joan Venge
A: 

Your code is correct, but it is not very efficient. You could instead use a HashSet<T> like this:

HashSet<Cluster> clusterSet = new HashSet<T>();
foreach (Cluster cluster in clustersByProgramme)
  clusterSet.Add(cluster);

In this case, also make sure that if cluster1 == cluster2, then

cluster1.Equals(cluster2);
cluster2.Equals(cluster1); //yeah, could be different depending on your impl
cluster1.GetHashCode() == cluster2.GetHashCode();
Martin Liversage
A: 

why not just use dictionary?

It is n(1) as long as your items have a good hash.

Seems a simple solution

Ie dictionary.Contains(key) is n(1)

you can then update existing if at all or add new

John Nicholas