SortedList - Sort by VALUE (not KEY)

G

gerrod

Hi -

Does anyone know a way to created a SortedList (in the
System.Collections namespace) that will sort on VALUES instead of
KEYS... ?

The scenario is this - I have a SortedList containing key-value pairs
of UserID - DisplayName for a whole bunch of user objects. The UserID
is simply a long, the DisplayName is something like, "Jones, Bill". I
want the SortedList to sort the names alphabetically, rather than by
increasing order of UserIDs.

The simple answer is to use the DisplayName as a key, and UserID as a
value. However this barfs if I have multiple people with the same
DisplayName, as you can't have duplicate keys in a SortedList.

I know that I can override the IComparer that the SortedList uses for
comparisons, however, logistically I cannot think of a way to create
an IComparer that will be able to access the VALUES of the SortedList
collection. The problem is that I MUST supply the IComparer at
construction time of the SortedList; however the IComparer needs to
know about the SortedList so that when it is supplied with 2 keys to
sort, it can then access the values of the collection to work out
which comes before the other. And of course, I can't do something like
this -

SortedList sList = new SortedList(new MyComparer(sList));

for (hopefully) obvious reasons...

The other thing I tried was creating a "wrapper class" like this -

class SortedUserList : IComparer {
private SortedList userList = null;

public SortedList UserList {
get {
if (userList == null) {
userList = new SortedList(this);
}

return userList;
}
}

public SortedUserList() {
}

#region IComparer Members

public int Compare(object x, object y) {
string first = UserList[x] as string;
string second = UserList[y] as string;

return first.CompareTo(second);
}

#endregion
}

But this also didn't work - I got a Stack Overflow when I tried to add
the second user into the list.

I'm really hoping that there is a simple solution to this problem.

Thanks for your help,
gerrod
 
R

Ray Hsieh (Djajadinata)

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

No you can't just pass in a Comparator, because in SortedList, it is
automatically applied to the keys instead of the values, no matter what
you do (and that's the way it is supposed to work anyway...)

An easy way would be to preserve the link between the key and the value
yourself, e.g.: in a struct, like a short program below, and then make
it implement IComparable to sort it based on user names. Then, a simple
ArrayList will do from there (see below)

using System;
using System.Collections;

class MainClass
{
~ public static void Main(string[] args) {
~ ArrayList users = new ArrayList();

~ users.Add(new User(1000, "Set"));
~ users.Add(new User(1004, "List"));
~ users.Add(new User(1002, "Gerrod"));
~ users.Add(new User(1003, "Map"));

~ users.Sort();

~ foreach (User user in users) {
~ Console.WriteLine(user.Id + ", " + user.Name);
~ }
~ }
}

struct User : IComparable {
~ private long _id;
~ private string _name;

~ public User(long id, string name) {
~ _id = id;
~ _name = name;
~ }

~ public long Id {
~ get {
~ return _id;
~ }
~ }

~ public string Name {
~ get {
~ return _name;
~ }
~ }

~ public int CompareTo(object obj) {
~ if(obj == null) {
~ return 1;
~ }
~ User that = (User)obj;
~ return this._name.CompareTo(that._name);
~ }
}


gerrod wrote:

| Hi -
|
| Does anyone know a way to created a SortedList (in the
| System.Collections namespace) that will sort on VALUES instead of
| KEYS... ?
|
| The scenario is this - I have a SortedList containing key-value pairs
| of UserID - DisplayName for a whole bunch of user objects. The UserID
| is simply a long, the DisplayName is something like, "Jones, Bill". I
| want the SortedList to sort the names alphabetically, rather than by
| increasing order of UserIDs.
|
| The simple answer is to use the DisplayName as a key, and UserID as a
| value. However this barfs if I have multiple people with the same
| DisplayName, as you can't have duplicate keys in a SortedList.
|
| I know that I can override the IComparer that the SortedList uses for
| comparisons, however, logistically I cannot think of a way to create
| an IComparer that will be able to access the VALUES of the SortedList
| collection. The problem is that I MUST supply the IComparer at
| construction time of the SortedList; however the IComparer needs to
| know about the SortedList so that when it is supplied with 2 keys to
| sort, it can then access the values of the collection to work out
| which comes before the other. And of course, I can't do something like
| this -
|
| SortedList sList = new SortedList(new MyComparer(sList));
|
| for (hopefully) obvious reasons...
|
| The other thing I tried was creating a "wrapper class" like this -
|
| class SortedUserList : IComparer {
| private SortedList userList = null;
|
| public SortedList UserList {
| get {
| if (userList == null) {
| userList = new SortedList(this);
| }
|
| return userList;
| }
| }
|
| public SortedUserList() {
| }
|
| #region IComparer Members
|
| public int Compare(object x, object y) {
| string first = UserList[x] as string;
| string second = UserList[y] as string;
|
| return first.CompareTo(second);
| }
|
| #endregion
| }
|
| But this also didn't work - I got a Stack Overflow when I tried to add
| the second user into the list.
|
| I'm really hoping that there is a simple solution to this problem.
|
| Thanks for your help,
| gerrod


- --
Ray Hsieh (Djajadinata)
ray underscore usenet at yahoo dot com
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (MingW32)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQE/nIkiwEwccQ4rWPgRAqn+AJ402SGnegA2+hvAOFQf+3PvfI5yiQCfYAk4
cXPzlQMWMVXcpDbSsNK103w=
=tjwy
-----END PGP SIGNATURE-----
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top