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

发布于 2024-07-24 21:58:55 字数 633 浏览 6 评论 0原文

这已经困扰我一段时间了。 我尝试了几种方法,但没有一种能正常工作。

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

这很容易。 问题是,每当用户加入或离开频道时都需要添加此列表,因此他们的用户名必须在离开时从列表中删除,并在他们重新加入时重新添加到正确的位置。

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

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

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

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

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

在这里询问是最后的手段,如果有人可以帮助我,我将非常感激。 先感谢您。

This has been bugging me for some time now. I've tried several approaches and none have worked properly.

I'm writing and IRC client and am trying to sort out the list of usernames (which needs to be sorted by a users' access level in the current channel).

This is easy enough. Trouble is, this list needs to added to whenever a user joins or leaves the channel so their username must be removed the list when the leave and re-added in the correct position when they rejoin.

Each users' access level is signified by a single character at the start of each username. These characters are reserved, so there's no potential problem of a name starting with one of the symbols. The symbols from highest to lowest (in the order I need to sort them) are:
~
&
@
%
+

Users without any sort of access have no symbol before their username. They should be at the bottom of the list.

For example: the unsorted array could contain the following:
~user1 ~user84 @user3 &user8 +user39 user002 user2838 %user29

And needs to be sorted so the elements are in the following order:
~user1 ~user84 &user8 @user3 %user29 +user39 user002 user2838

After users are sorted by access level, they also need to be sorted alphabetically.

Asking here is a last resort, if someone could help me out, I'd very much appreciate it.
Thankyou in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

昇り龍 2024-07-31 21:58:55

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

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

As long as the array contains an object then implement IComparable on the object and then call Array.Sort().

Tho if the collection is changable I would recommend using a List<>.

甜心小果奶 2024-07-31 21:58:55

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

You can use SortedList<K,V> with the K (key) implementing IComparable interface which then defines the criteria of your sort. The V can simply be null or the same K object.

叹梦 2024-07-31 21:58:55

您可以为 Array.Sort 提供 IComparerComparison。 那么你只需要自己实现比较即可。 如果这是一个相对复杂的比较(听起来像这样),我会在一个单独的类中实现 IComparer,您可以轻松地对其进行单元测试。 然后调用:

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

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

Array.Sort(userNames, UserNameComparer.Instance);

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

事实上,听起来您并不经常需要实际进行完整排序。 删除用户不会改变排序顺序,插入仅意味着在正确的位置插入。 换句话说,您需要:

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

您可以使用 Array.BinarySearch 完成最后一步或 List.BinarySearch,它再次允许您指定自定义 IComparer。 一旦您知道在哪里插入用户,您就可以相对便宜地做到这一点(与再次对整个集合进行排序相比)。

You can give an IComparer<T> or a Comparison<T> to Array.Sort. Then you just need to implement the comparison yourself. If it's a relatively complex comparison (which it sounds like this is) I'd implement IComparer<T> in a separate class, which you can easily unit test. Then call:

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

You might want to have a convenient instance defined, if UserNameComparer has no state:

Array.Sort(userNames, UserNameComparer.Instance);

List<T> has similar options for sorting - I'd personally use a list rather than an array, if you're going to be adding/removing items regularly.

In fact, it sounds like you don't often need to actually do a full sort. Removing a user doesn't change the sort order, and inserting only means inserting at the right point. In other words, you need:

  • Create list and sort it to start with
  • Removing a user is just a straightforward operation
  • Adding a user requires finding out where to insert them

You can do the last step using Array.BinarySearch or List.BinarySearch, which again allow you to specify a custom IComparer<T>. Once you know where to insert the user, you can do that relatively cheaply (compared with sorting the whole collection again).

橘亓 2024-07-31 21:58:55

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

You should take a look at the IComparer interface (or it's generic version). When implementing the CompareTo method, check whether either of the two usernames contains one of your reserved character. If neither has a special reserved character or both have the same character, call the String.CompareTo method, which will handle the alphabetical sorting. Otherwise use your custom sorting logic.

莫言歌 2024-07-31 21:58:55

我尝试了排序,并提出了以下排序方法:

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);                       
               });

此比较代码也可以存在于 IComparer 实现的 Compare 方法中。

I gave the sorting a shot and came up with the following sorting approach:

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);                       
               });

This comparison code can just as well live inside the Compare method of an IComparer<T> implementation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文