views:

4931

answers:

8

I'm storing a bunch of supposedly-unique item IDs as a key and the file locations as the value in a hash table while traversing a table. While I am running through it, I need to make sure that they key/location pair is unique or throw an error message. I have the hashtable set up and am loading the values, but am not sure what to test:

Hashtable check_for_duplicates = new HashTable();
foreach (object item in items)
{
    if (check_for_duplicates.ContainsKey(item["ItemID"]) &&
        //what goes here?  Would be contains item["Path"] as the value for the key)
    {
        //throw error
    }
}
+4  A: 

If you were using Dictionary instead, the TryGetValue method would help. I don't think there is a really better way for the pretty much deprecated Hashtable class.

object value;
if (dic.TryGetValue("key", out value) && value == thisValue)
  // found duplicate
Mehrdad Afshari
which namespace should I use to enable Dictionaries? They're not in any of the default namespaces.
Brian
The Dictionary class (http://msdn.microsoft.com/en-us/library/xfhwa508.aspx) was introduced in .NET 2.0 and is located in the System.Collections.Generic namespace.
Mike Rosenblum
+2  A: 
if (check_for_duplicates.ContainsKey(item["ItemID"]) &&
    check_for_duplicates[item["ItemID"]] == item["Path"])
{
    //throw error
}
Ken Browning
+4  A: 

Try this:

Hashtable check_for_duplicates = new HashTable();
foreach (object item in items)
{
    if (check_for_duplicates.ContainsKey(item["ItemID"]) &&
        check_for_duplicates[item["ItemID"]].Equals(item["Path"]))
    {
        //throw error
    }
}

Also, if you're using .NET 2.0 or higher, consider using Generics, like this:

List<Item> items; // Filled somewhere else

// Filters out duplicates, but won't throw an error like you want.
HashSet<Item> dupeCheck = new HashSet<Item>(items); 

items = dupeCheck.ToList();

Actually, I just checked, and it looks like HashSet is .NET 3.5 only. A Dictionary would be more appropriate for 2.0:

Dictionary<int, string> dupeCheck = new Dictionary<int, string>();

foreach(Item item in items) {
    if(dupeCheck.ContainsKey(item.ItemID) && 
       dupeCheck[item.ItemID].Equals(item.Path)) {
        // throw error
    }
    else {
        dupeCheck[item.ItemID] = item.Path;
    }    
}
Chris Doggett
Found a minor error:check_for_duplicates[item["ItemID"]] == item["Path"] should becheck_for_duplicates[item["ItemID"]].Equals(Item["Path"])
Brian
Regarding HashSet; you can compare the count in the resulting set with the count of the original collection if you want to figure out whether there were dupes. (Warning: not performant.)
mquander
+1  A: 

It kinda depends what the items array is... you'll want something like:

check_for_duplicates.ContainsValue(item["Path"]);

Assuming that the item is some form of lookup. Really you need to be casting item, or using a type system to actually access any values via an index.

Ian
My bad... I hadn't realised that there was an AND clause in the original question.
Ian
+2  A: 

ContainsKey is the best method.

If you aren't forced to use .NET 1.1 I would use the Dictionary introduced in .NET 2.0.

It is much better than a Hashtable from performance and is strongly typed.

Dictionary<string, int> betterThanAHash = new Dictionary<string, int>();

betterThanAHash.ContainsKey("MyKey");
David Basarab
Which namespace should I use for this? Dictionary isn't in the default namespaces I'm using.
Brian
then add the namespace for Dictionary =)
Svish
@Brian - System.Collections.Generic
TheMissingLINQ
+2  A: 
Hashtable check_for_duplicates = new HashTable();

foreach (object item in items) 
{
    if (check_for_duplicates.ContainsKey(item["ItemID"]) && check_for_duplicates[item["ItemID"]] == item["Path"])
    {
        //throw error
    } 
}

I do believe this is what you're looking for.

EDIT - Looks like I was beaten to the punch :P

Matt Grande
Almost, your example doesn't quite work (missing a ] on:check_for_duplicates[item["ItemID"]
Brian
That's correct, it's been fixed.
Matt Grande
+1  A: 

Why not use a Dictionary instead?

That will throw an ArgumentException if you try to Add a key that already exists in the Dictionary.

That way you can catch the duplicate at the moment it is being added, rather than performing a check_for_duplicates test later.

GrahamS
+1  A: 

You didn't say what version of things you were using. Is there a reason you must use a Hashtable vs a HashSet? You would have no need to check for duplicates if your data structure didn't allow them. See also:

http://www.vcskicks.com/csharp_data_structures2.html

Other than that, the question of how to accomplish the same thing in Hashtable has already been answered here. I'm just pointing out that you don't need to do all the pathological checking if you forbid it in the first place.

Jason Stelzer