Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / November 2006

Tip: Looking for answers? Try searching our database.

Help! Need to sorted collection accessible by key

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Burt - 21 Nov 2006 02:08 GMT
I need to create a collection of classes (or structures) can be
accessed by a string key, eg MyColl("ShortName5").Name for class with
key ShortName5. But it also has to be sorted by a second ordering
field.

Hashtable offers access by key, but is not sorted. Arraylist is sorted
(the fields will come presorted from the db), but I can't access by
key. SortedList can't be sorted by a field different from the key
field.

Can anyone think of a solution? Thanks for any help. Using .Net 1.1.

Burt
KH - 21 Nov 2006 04:43 GMT
Create your own type for the key that implements IComparable, and override
Equals() and GetHashCode(), then return the hashcode of the key you want
access with, and compare (sort) by the one you want to order by, and put it
in SortedList; quickly:

class MyKey : IComparable
{
   MyKey(string comparer, string hasher)
   {
        this._comparer = comparer;
        this._hasher = hasher;
   }

   override bool Equals(MyKey other)
   {
        return (this._comparer == other._comparer);
   }

   override int GetHashCode()
   {
       return this._hasher.GetHashCode();
   }

   int CompareTo(MyKey other)
   {
        return this._comparer.CompareTo(other._comparer);
   }
};

> I need to create a collection of classes (or structures) can be
> accessed by a string key, eg MyColl("ShortName5").Name for class with
[quoted text clipped - 9 lines]
>
> Burt
Bruce Wood - 21 Nov 2006 05:56 GMT
> Create your own type for the key that implements IComparable, and override
> Equals() and GetHashCode(), then return the hashcode of the key you want
[quoted text clipped - 24 lines]
>     }
> };

This is unlikely to work, or at least will work under restricted
circumstances.

Hashtable uses the Equals method to decide if two items are equal,
since GetHashCode may return the same code for more than one item.

So, this will work ONLY if the _comparer and the _hasher are such that
if two items compare as equal by the _comparer key then they also
compare equal by the _hasher key. Let's look at what happens if this is
not true.

If two items that compare equal using the _hasher key do not compare
equal with the _comparer key, then Hashtable will put duplicate entries
in the table for that item, since the second item to be hashed will
hash to the same bucket in the hash table but will not be equal to
anything in the chain. So this:

MyKey key1 = new MyKey("A", "A");
MyKey key2 = new MyKey("B", "A");
myHashtable[key1] = obj1;
myHashtable[key2] = obj2;

may result in two entries in the hash table even though the "hasher"
key of both key1 and key2 are the same.

Conversely, if two items that compare equal using the _comparer key do
not compare equal with the _hasher key, then they may result in only
one entry in the Hashtable if by chance the two _hasher keys hash to
the same code (and thus the same hash table bucket), since the second
object to be hashed will be equal to an item already in the chain.

I would suggest instead that you create your own data structure backed
by a Hashtable and either a SortedList or your own sorted list
implementation. Here's a rough idea:

public class MyCollection
{
   private Hashtable _hash;
   private SortedList _list;

   public MyCollection(int capacity)
   {
       this._hash = new Hashtable(capacity);
       this._list = new SortedList(capacity);
   }

   public MyCollection() : this(10) {  }

   public object this[string hashKey]
   {
       get { return this._hash[hashKey]; }
   }

   public object this[int index]
   {
       get { return this._list[index]; }
   }

   public IDictionaryEnumerator GetEnumerator() { return
this._list.GetEnumerator(); }

   public object this[string hashKey, string listKey]
   {
       get
       {
           object hashObj = this._hash[hashKey];
           object listObj = this._list[listKey];
           if (hashObj != listObj) { throw new
ArgumentException(String.Format("Hash key '{0}' and list key '{1}'
indicate different elements.", hashKey, listKey), "listKey"); }
           return hashObj;
       }

       set
       {
           this._hash[hashKey] = value;
           this._list[listKey] = value;
       }
   }
}

Of course, you can define more methods, and the semantics are really up
to you. (For example, if you say myStructure["key"] do you mean the
hash table key or the list key? Or perhaps the caller must always
specify both keys? Or perhaps you supply functions, not indexers, to
allow the caller to look in either table?) This was just a quick sketch
of what is possible.
Chester - 21 Nov 2006 05:07 GMT
Hi Burt,

Check -
http://www.codeproject.com/csharp/hashlistarticle.asp

HTH

Cheers,
Chester

> I need to create a collection of classes (or structures) can be
> accessed by a string key, eg MyColl("ShortName5").Name for class with
[quoted text clipped - 9 lines]
>
> Burt
Marc Gravell - 21 Nov 2006 06:15 GMT
SortedList also has GetByKey that may be of interest

Marc
Marc Gravell - 21 Nov 2006 06:16 GMT
Oops; meant GetByIndex!! the indexer (this[object]) provides "by key"

Marc
Burt - 24 Nov 2006 01:31 GMT
Thanks everyone for the  great ideas. I ended up trying  to create my
own key class for a couple of hours, but couldn't make it work (kept
getting IComparer errors when accessing by key, even though the key
class implemented IComparable. I think the sorted list was looking to
the object, not the key).

I ended up just holding a second arraylist in memory in the right order
and accessing the sortedlist by looping through that. I believe .net
2.0 has a collection that will solve the  problem when I upgrade.

Thanks again,

Burt

> Oops; meant GetByIndex!! the indexer (this[object]) provides "by key"
>
> Marc

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.