CodeSmith Community
Your Code. Your Way. Faster!

Wanted: A sorted-hashtable collection

Latest post 10-12-2004 10:16 PM by mimo. 5 replies.
  • 04-14-2004 3:43 PM

    Wanted: A sorted-hashtable collection

    Hi,
    I'm looking for a hashtable style collection (to access items by a unique key), however I also want to iterate through the collection (for-each) in a sorted way based on a key that is not the same as the unique key and which may also contain duplicates. Any recommendations?
     
    I've already tried converting the hashtable's 'values' member to an array and sorting that - but that does not result in a typed result set.
     
    Any suggestions?
     
    Best regards
    Steve
     
     
    • Post Points: 120
  • 04-15-2004 9:46 PM In reply to

    • cnahr
    • Top 50 Contributor
    • Joined on 06-03-2003
    • Posts 105
    • Points 2,275

    RE: Wanted: A sorted-hashtable collection

    Steve, I'm not aware of any collection class that does that, either template or standard .NET collection or even STL.
     
    The SortedList class/template does sort by key but that's still only one key. If you want to sort by multiple keys you basically have to create an ArrayList and define your own IComparable implementation(s) to sort by whatever key(s) you want.
     
    You're sure you don't want to use a real database backend for that job? Sorting by arbitrary fields is what SQL was designed for.
     
    Cheers, Chris
    • Post Points: 5
  • 04-16-2004 7:31 AM In reply to

    RE: Wanted: A sorted-hashtable collection

    Hi Chris,
    This class is (would) be used in the following scenario:

    I have an Order business object which loads a hashtable of OrderItem business objects. When I display the order I want the OrderItems to be sorted. When I'm processing a single OrderItem it's referenced using it's primary key ID.

    I could go back to the database but that would be another round trip which is expensive. I already have the objects 'in memory'.

    If I was doing this in C++ I would store pointers to the objects in a sorted list and a hashtable to optimize the memory use.

    I do make use of the XSLT sorting mechanism which works well for most output, but it doesn't work when I want to build an ASP.Net form from server side controls.

    Best regards
    Steve
    • Post Points: 5
  • 04-17-2004 12:23 AM In reply to

    • Lavos
    • Top 50 Contributor
    • Joined on 02-04-2004
    • Posts 110
    • Points 2,390

    RE: Wanted: A sorted-hashtable collection

    You can still store pointers/references in a separate sorted list. You could even make a typed pair type object to store as the item in the sorted collection that has the key and object, assuming your key doesn't come from the object.
    • Post Points: 5
  • 04-17-2004 9:46 AM In reply to

    RE: Wanted: A sorted-hashtable collection

    Hi Jason,

    One nice thing about C++ is that you can be sure when you're working with a pointer or the object itself. How do you make that distinction in VB.Net?

    I know I can pass byref but if I create two arraylist objects in VB.Net and I add a object to both arraylists' how do I know if I'm storing copies of the objects or references to them.

    From experience it can be either...as sometimes making modifications to an object affects the objects in the list sometimes not...all very unpredictable...

    Cheers

    Steve

     

    • Post Points: 5
  • 04-17-2004 4:24 PM In reply to

    • Lavos
    • Top 50 Contributor
    • Joined on 02-04-2004
    • Posts 110
    • Points 2,390

    RE: Wanted: A sorted-hashtable collection

    With dotnet, if it's a reference type you are, more or less, always working with a "pointer".

    With value types (for instance, structures) you are generally working with copies of the original if you pass it through a method or as a return'ed value.

    For instance, if you put the same DataSet in 2 different ArrayLists, they both are holding references to the same DataSet.

    If you put the same structure in 2 different ArrayLists, generally there are going to be 3 copies of the structure. (one probably on the stack, and 1 boxed copy in the heap for each ArrayList.)

    So, moral of the story, usually use reference objects and you won't have to worry about the extraneous copies :)
    • Post Points: 5
  • 10-12-2004 10:16 PM In reply to

    • mimo
    • Not Ranked
    • Joined on 10-12-2004
    • Posts 1
    • Points 5

    RE: Wanted: A sorted-hashtable collection

    I ran into a similar situation where I needed a hastable sorted on different values, and could not easily use a database to do the sort.
     
    Eric Gunnerson as it turns out had published an article on MSDN for improving foreach - he wanted to have a similar facility as found in perl for sorting using foreach...
     
    Something else that's common when dealing with data in a hashtable is wanting to order the entries based on the values in the hashtable. We'd like to be able to use the same IComparable approach as we used previously, but that takes a little more work. What we need is a class that has an IComparable implementation that looks up the hashtable values from the keys, and then compares those values.
    This is done by creating another class named SortHashValueItem. An instance of this class is created for each key in the hashtable, storing the hashtable key, the hashtable reference, and an IComparer object (if applicable). This class implements IComparable, and the CompareTo() function forwards the comparison to the values in the hashtable or the IComparer.

     
     
    So - I have used his code, and the code from CodeSmith to make a hashtable that has a sort method on it. Its probably terribly inefficient (time constraints, refactor when I have the opportunity) but it works.
     
    Caveats aside - on the hashtable, which stores a collection of Participants for an event, I have created a set of sort methods for each value I want to sort on. I use Erics method of sorting using foreach, and a custom comparer to sort the hashtable into an arraylist, which is then returned.
     
    First, I populate the collection, then generate a sorted version of it sorting on whatever parameter required by calling the appropriate method. This returns an arraylist of the contents of the hashtable sorted on in this case the last name. The arraylist can then be bound to a control etc.

    ParticipantCollection registeredParticipants = ParticipantCollection.Find(m_currentOrgID, myEvent, true);

    ArrayList sortedParticipants = registeredParticipants.SortLastName();
     
    Sort method on ParticipantCollection - uses an Eric Gunnerson IterSortHashValue class, typed to the class I am using:
    #region Sort Methods
    #region (Method) SortLastName
    /// <summary>
    /// Sorts the contents of the collection based on the last name
    /// A better way of implimenting this is required.
    /// </summary>
    /// <returns>Returns an arraylist of participants from the collection sorted by last name</returns>
    public ArrayList SortLastName()
    {
    ArrayList sortedItems = new ArrayList();
    foreach (int participantID in new ParticipantCollectionSort(this, new ParticipantComparer()))
    {
    sortedItems.Add(this[participantID]);
    }
    return sortedItems;
    }
    #endregion
    ParticipantComparer class:
    #region (Class) ParticipantComparer
    /// <summary>
    /// ParticipantComparer - defines allowable comparisions to be made between participant objects.
    /// This class is used to assist in sorting by defining what property to use to do the sort
    /// </summary>
    public class ParticipantComparer: IComparer
    {
    /// <summary>
    /// Compare Participant objects based on the LastName property. The implimentation IComparer requires
    /// type Object to be passed in. The method internally defines that Participant objects are the only
    /// type allowable
    /// </summary>
    /// <param name="x">Participant Object</param>
    /// <param name="y">Participant Object</param>
    /// <returns></returns>
    public int Compare(object x, object y)
    {
    if (!(x is Participant && y is Participant))
    {
    throw new ArgumentException
    ("The objects to compare must be of type 'Participant'");
    }
    string tempObj1 = ((Participant)x).LastName;
    string tempObj2 = ((Participant)y).LastName;
    return tempObj1.ToString().CompareTo (tempObj2.ToString ());
    }
    }
    #endregion
     ParticipantCollectionSort - from Eric Gunnerson's Iter collection code (typed again)
    using System;
    using System.Collections;
    namespace DomainModel
    {
    /// <summary>
    /// Iterate the keys in a hashtable, ordering them by the values
    /// corresponding to those keys. Either uses the defined ordering on the
    /// values or a passed-in IComparer implementation
    /// </summary>
    public class ParticipantCollectionSort: IEnumerable
    {
    internal class IterSortHashValueEnumerator: IEnumerator
    {
    ArrayList items = new ArrayList();
    int currentItem;
    internal IterSortHashValueEnumerator(ParticipantCollection hashtable, IComparer comparer)
    {
    // create a new SortHashValueItem for each key.
    foreach (int key in hashtable.Keys)
    {
    SortHashValueItem item = new SortHashValueItem(hashtable, key, comparer);
    items.Add(item);
    }
    currentItem = -1;
    items.Sort();
    }
    public void Reset()
    {
    currentItem = -1;
    }
    public bool MoveNext()
    {
    currentItem++;
    if (currentItem == items.Count)
    return false;
    return true;
    }
    public object Current
    {
    get
    {
    SortHashValueItem current = (SortHashValueItem) items[currentItem];
    return current.Key;
    }
    }
    }
    // item to hold a key and the related hash table
    internal class SortHashValueItem: IComparable
    {
    ParticipantCollection hashtable;
    int key;
    IComparer comparer;
    public SortHashValueItem(ParticipantCollection hashtable, int key, IComparer comparer)
    {
    this.hashtable = hashtable;
    this.key = key;
    this.comparer = comparer;
    }
    public object Key
    {
    get
    {
    return key;
    }
    }
    public int CompareTo(object object2)
    {
    SortHashValueItem item2 = (SortHashValueItem) object2;
    // get the two values for these keys...
    object value1 = hashtable[key];
    object value2 = item2.hashtable[item2.key];
    if (comparer != null)
    {
    return comparer.Compare(value1 ,value2);
    }
    else
    {
    // compare one to another. They must implement IComparable...
    IComparable comparable = (IComparable) value1;
    return comparable.CompareTo(value2);
    }
    }
    }
    /// <summary>
    /// Create an instance of the IterSortHashValue class
    /// </summary>
    /// <param name="hashtable">The hashtable to use</param>
    public ParticipantCollectionSort(ParticipantCollection hashtable)
    {
    this.hashtable = hashtable;
    }
    /// <summary>
    /// Create an instance of the IterSortHashValue class, using a
    /// specific comparer
    /// </summary>
    /// <param name="hashtable">The hashtable to use</param>
    /// <param name="comparer">The comparer to use</param>
    public ParticipantCollectionSort(ParticipantCollection hashtable, IComparer comparer)
    {
    this.hashtable = hashtable;
    this.comparer = comparer;
    }
    public IEnumerator GetEnumerator()
    {
    return new IterSortHashValueEnumerator(hashtable, comparer);
    }
    ParticipantCollection hashtable;
    IComparer comparer;
    }
    }
     
    • Post Points: 5
Page 1 of 1 (7 items) | RSS
Copyright © 2008 CodeSmith Tools, LLC
Powered by Community Server (Commercial Edition), by Telligent Systems