tags:

views:

215

answers:

6

I'm wondering if there is an IList<T> implementation that's backed by a hash like HashSet<T> but offers indexed access?

To be clear, I'm not concerned on how to implement one, just wondering if anyone knows if it's already available.

A: 

KeyedCollection<TKey, TItem> provides this type of functionality, though you do have to derive from it and provide it with a function to extract a key from the item which is hashed.

Greg Beech
This wouldn't serve as a hash backed `IList<T>` implementation as it requires the key to be unique and doesn't allow duplicate items.
Brett Ryan
A: 

You can have any number of (hashed or other) indexes into doubly linked list nodes (doubly linked so you have O(1) deletion).

wrang-wrang
A: 

There is none in .Net 3.5, but its very easy to implement one:

public class Set<T> : KeyedCollection<T,T>
{
    public Set()
    {}

    public Set(IEnumerable<T> collection)
    {
        foreach (T elem in collection)
        {
            Add(elem);
        }
    }

    protected override T GetKeyForItem(T item)
    {
        return item;
    }
}
Grzenio
+2  A: 

You could implement IList<T> yourself and keep two backing collections - a List<T> and a HashSet<T>. Basically get Visual Studio to provide a "throw exception" implementation for everything in IList<T>, then for each method work out whether you want to proxy it to the list or the set.

Of course you'd have to be careful for duplicates etc (define the behaviour of Add(x), Add(x), Remove(x), Contains(x) - you could end up with it in the list but not the set) but it wouldn't be too hard.

Jon Skeet
That's how I'm doing it at the moment, I have an IList<T> implementation that has a hash based backing table to allow close-to O(1) Contains(T) and IndexOf(T) operations.
Brett Ryan
Right. IndexOf is significantly harder than Contains of course...
Jon Skeet
A: 

HashSet<T> implements ICollection<T>, if that's any use. Available from 3.5 onwards.

Cameron MacFarland
Yep, but again, it's not an `IList<T>`.
Brett Ryan
Sure, just didn't know if you could get away with ICollection instead of IList.
Cameron MacFarland
+1  A: 

Quick answer - no, it is not already available.

Implementing it is of course easy as you realise. The reason why it is not commonly implemented is as follows. If you can do contains in O(1) then you could do index lookup in O(1). But of course index lookup is not unique if you have duplicate elements.

As what you essentially need is two data structures, a Set (or Map) and a List, and there isn't a much more efficient way of doing it than this, the standard library authors leave you to combine the data-structures yourself.

Nick Fortescue
Thanks Nick, it could be argued that a `HashSet<T>` also requires two data structures, it would require a backing table also, yet it's a very useful structure, and as soon as I started using 3.5 I replaced my own implementation with it.
Brett Ryan
I'd argue a HashSet is a single data-structure, a table (though some use linked lists as well). But an implementation which tried to do everything would be too bloated for most people's use, and an implementation which only did contains quickly would lead to people moaning about indexOf etc.
Nick Fortescue