自定义C#数组的排序顺序

时间:2009-06-24 09:45:18

标签: c# arrays sorting irc

这一直困扰着我一段时间。我尝试了几种方法,没有一种方法可以正常使用。

我正在写和IRC客户端,我正在尝试整理用户名列表(需要按照当前频道中用户的访问级别进行排序)。

这很容易。麻烦的是,每当用户加入或离开频道时,都需要添加此列表,以便在离开时必须将其用户名移除,并在重新加入时重新添加到正确的位置。

每个用户的访问级别由每个用户名开头的单个字符表示。这些字符是保留的,因此不存在以其中一个符号开头的名称的潜在问题。从最高到最低的符号(按我需要排序的顺序)是: 〜 &安培; @ % +

没有任何访问权限的用户在其用户名之前没有符号。它们应该在列表的底部。

例如:未排序的数组可能包含以下内容: ~user1~user84 @ user3& user8 + user39 user002 user2838%user29

需要进行排序,以便元素按以下顺序排列: ~user1~user84& user8 @ user3%user29 + user39 user002 user2838

用户按访问级别排序后,还需要按字母顺序排序。

问这里是最后的手段,如果有人可以帮助我,我会非常感激。 谢谢你提前。

5 个答案:

答案 0 :(得分:1)

只要数组包含一个对象,然后在对象上实现IComparable,然后调用Array.Sort()。

如果集合是可变的,我建议使用List<>。

答案 1 :(得分:1)

您可以使用SortedList<K,V>与K(密钥)实现IComparable接口,然后定义排序条件。 V可以简单地为null或相同的K对象。

答案 2 :(得分:1)

您可以将IComparer<T>Comparison<T>提供给Array.Sort。然后你只需要自己实现比较。如果这是一个相对复杂的比较(听起来像这样)我会在一个单独的类中实现IComparer<T>,您可以轻松地进行单元测试。然后致电:

Array.Sort(userNames, new UserNameComparer());

如果UserNameComparer没有状态,您可能希望定义一个方便的实例:

Array.Sort(userNames, UserNameComparer.Instance);

List<T>有类似的排序选项 - 如果您要定期添加/删除项目,我个人会使用列表而不是数组。

事实上,听起来你并不经常需要真正做一个完整的排序。删除用户不会更改排序顺序,而插入只意味着插入正确的位置。换句话说,你需要:

  • 创建列表并将其排序以
  • 开头
  • 删除用户只是一个简单的操作
  • 添加用户需要找到插入位置

您可以使用Array.BinarySearchList.BinarySearch执行最后一步,这又允许您指定自定义IComparer<T>。一旦你知道在哪里插入用户,你可以相对便宜地做到这一点(与再次整理整个集合相比)。

答案 3 :(得分:0)

您应该查看IComparer界面(或generic version)。实现CompareTo方法时,请检查两个用户名中的任何一个是否包含一个保留字符。如果两者都没有特殊的保留字符或两者都具有相同的字符,请调用String.CompareTo方法,该方法将处理字母排序。否则使用自定义排序逻辑。

答案 4 :(得分:0)

我给了排序一个镜头并提出了以下排序方法:

List<char> levelChars = new List<char>();
levelChars.AddRange("+%@&~".ToCharArray());
List<string> names = new List<string>();
names.AddRange(new[]{"~user1", "~user84",  "@user3", "&user8", "+user39", "user002", "user2838", "%user29"});
names.Sort((x,y) =>
               {
                   int xLevel = levelChars.IndexOf(x[0]);
                   int yLevel = levelChars.IndexOf(y[0]);

                   if (xLevel != yLevel)
                   {
                       // if xLevel is higher; x should come before y
                       return xLevel > yLevel ? -1 : 1;
                   }

                   // x and y have the same level; regular string comparison
                   // will do the job
                   return x.CompareTo(y);                       
               });

此比较代码也可以在Compare实现的IComparer<T>方法中生效。