这一直困扰着我一段时间。我尝试了几种方法,没有一种方法可以正常使用。
我正在写和IRC客户端,我正在尝试整理用户名列表(需要按照当前频道中用户的访问级别进行排序)。
这很容易。麻烦的是,每当用户加入或离开频道时,都需要添加此列表,以便在离开时必须将其用户名移除,并在重新加入时重新添加到正确的位置。
每个用户的访问级别由每个用户名开头的单个字符表示。这些字符是保留的,因此不存在以其中一个符号开头的名称的潜在问题。从最高到最低的符号(按我需要排序的顺序)是: 〜 &安培; @ % +
没有任何访问权限的用户在其用户名之前没有符号。它们应该在列表的底部。
例如:未排序的数组可能包含以下内容: ~user1~user84 @ user3& user8 + user39 user002 user2838%user29
需要进行排序,以便元素按以下顺序排列: ~user1~user84& user8 @ user3%user29 + user39 user002 user2838
用户按访问级别排序后,还需要按字母顺序排序。
问这里是最后的手段,如果有人可以帮助我,我会非常感激。 谢谢你提前。
答案 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.BinarySearch
或List.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>
方法中生效。