Search code examples
c#genericsiteratorhashtable

Iterator for custom Hashtable C#


I need to provide an iterator for my custom fixed sized hashtable class, I am storing the data in an array of linkedlist.

class HashTableNode<T1, T2>
{
    public T1 Key { get; set; }
    public T2 Value { get; set; }
}
class HashTableClass<T1, T2>
{
    public LinkedList<HashTableNode<T1, T2>>[] elements;
    const int defaultSize = 10000;
    
    public HashTableIterator<T1, T2> GetIterator()
    {
         return new HashTableIterator<T1, T2>(this);
    }
}

class HashTableIterator<T1, T2> 
{
    //need to implement this
}

For the iterator I need following functionalities:

  • HasNext() // tells if there is an element at current iterator position
  • Current // returns the value stored at current iterator position
  • MoveNext() // moves the iterator to next position
HashTableClass<int, string> hashtable = new HashTableClass<int, string>();
//Iterator will be used like this
HashTableIterator<int, string> iterator = hashtable.GetIterator();
while(iterator.HasNext())
{
    Console.Write(iterator.Current);
    iterator.MoveNext();
}


Solution

  • In .NET there is stadard IEnumerable pattern. Better to stay with this implementation. If you want to expose only values, you can do the following

    public class HashTableNode<T1, T2>
    {
        public T1 Key { get; set; }
        public T2 Value { get; set; }
    }
    
    public class HashTableClass<T1, T2>: IEnumerable<T2>
    {
        public LinkedList<HashTableNode<T1, T2>>[] elements;
        const int defaultSize = 10000;
    
        public IEnumerator<T2> GetEnumerator()
        {
            return elements.SelectMany(l => l).Select(e => e.Value).GetEnumerator();
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
    

    Or you can introduce methods which returns IEnumerable

    public IEnumerable<T2> GetValues()
    {
        return elements.SelectMany(l => l).Select(e => e.Value);
    }
    

    Or using yield return

    public IEnumerable<T2> GetValues()
    {
        foreach (var list in elements)
        {
            foreach (var node in list)
                yield return node.Value;
        }
    }
    

    In all cases, you can use foreach for your collection:

    var hashTable = ...
    
    foreach (var value in hashTable)
    {
        ...
    }
    
    foreach (var value in hashTable.GetValues())
    {
        ...
    }
    

    If you want to get "iterator" which is called IEnumerator in .NET, you can call IEnumerable.GetEnumerator()

    using var enumerator = hashTable.GetEnumerator();
    // or
    using var enumerator = hashTable.GetValues().GetEnumerator();
    
    while (enumerator.MoveNext())
    {
        Console.Write(enumerator.Current);
    }