【问题标题】:How to sort a list of char[]?如何对char []列表进行排序?
【发布时间】:2014-12-12 13:54:30
【问题描述】:

我有以下清单:

List<char[]> list1 = new List<char[]>();

我需要对它们上的所有 char[] 元素进行排序。如果我使用list1.Sort(),它说它无法比较元素,知道如何排序吗?

我真的需要列表是char[] 而不是string

【问题讨论】:

  • 您需要对每个数组单独排序还是将所有数组一起排序?
  • 所以你想对 char 数组进行排序,认为它是一个字符串,所以 ['A', 'B', 'C'] 将在 ['A', 'C' 之前, 'B']?
  • 如果你能给出一个简短但完整的例子来说明你想要达到的目标,那真的很有帮助。
  • 可能不快,但 list1.OrderBy( x => new String(x) ) 应该可以。
  • 您想如何对它们进行排序?可以举个例子吗?

标签: c# .net arrays list sorting


【解决方案1】:

如果您希望 char[] 在排序时具有与 string 相同的行为,您可以这样做:

list1 = list1.OrderBy(x => new string(x)).ToList();

【讨论】:

  • @Rawling:我想这是合乎逻辑的做法。
  • 这不会对list1 的值引用的现有列表进行排序。它返回一个新序列,但根本不修改现有列表。
  • 仍然没有修改现有列表:p(不是我的 DV,我很高兴等到 OP 澄清)
  • @Rawling:另外,关于“如果”:OP 说他不想使用 string 作为数据类型。看来他确实打算进行string 之类的排序,但这只是我的 2 美分。
  • 看起来你选择了...明智:)
【解决方案2】:

您也可以根据需要将List.Sortapproach of Patrick 一起使用:

list1.Sort((chars1, chars2) => new string(chars1).CompareTo(new string(chars2)));

那不需要创建一个新列表。

另一种方法是为Char[] 实现自己的IComparer&lt;T&gt;。这应该可以工作,尽管它肯定是可以改进和未经测试的。相关部分是Compare 方法:

public class CharArrayComparer : IComparer<Char[]>, IEqualityComparer<Char[]>
{
    public CharArrayComparer() : this(false) {  }
    public CharArrayComparer(bool ignoreCase)
    {
        IgnoreCase = ignoreCase;
    }
    public bool IgnoreCase { get; set; }

    public int Compare(char[] x, char[] y)
    {
        if (x == null && y != null) return -1;
        if (y == null && x != null) return 1;
        if (y == null && x == null) return 0;
        int minLength = Math.Min(x.Length, y.Length);
        for(int i = 0; i < minLength; i++)
        {
            char c1 = IgnoreCase ? char.ToUpperInvariant(x[i]) : x[i];
            char c2 = IgnoreCase ? char.ToUpperInvariant(y[i]) : y[i];
            if (c1 < c2) return -1;
            else if (c2 < c1) return 1;
        }

        return x.Length - y.Length;
    }

    public bool Equals(char[] x, char[] y)
    {
        if (x == null || y == null) return false;
        if (x.Length != y.Length) return false;
        for (int i = 0; i < x.Length; i++)
        {
            char c1 = IgnoreCase ? char.ToUpperInvariant(x[i]) : x[i];
            char c2 = IgnoreCase ? char.ToUpperInvariant(y[i]) : y[i];
            if (c1 != c2) return false;
        }

        return true;
    }

    public int GetHashCode(char[] chars)
    {
        if(chars == null) return 0;
        int hash = 17;
        unchecked
        {
            foreach (char c in chars)
            {
                if(IgnoreCase)
                    hash = hash * 31 + char.ToUpperInvariant(c).GetHashCode();
                else
                    hash = hash * 31 + c.GetHashCode();
            }
        }
        return hash;
    }
}

List.Sort 或许多 LINQ 扩展方法中很容易使用:

list1.Sort(new CharArrayComparer());

【讨论】:

  • 它确实需要构建更多的字符串......但我认为没有开箱即用的就地排序可以避免这种情况。
  • @Rawling:我尝试实现一个,但尚未经过测试。无论如何可能会有帮助。
  • @TimSchmelter - 感谢这个解决方案 - 为我节省了大量的开发工作。我唯一的意见是您可能希望将比较函数的最终返回语句更改为“返回 x.Length - y.Length;”因为如果 x 和 y 共享相同的字符直到最小长度,那么较长的 char 数组相对比较短的数组更大。
【解决方案3】:

对于使用 List.Sort(),列表元素应该是 comparable(实现可比较接口) 因此,如果您有特殊的比较,我更喜欢为元素创建一个新类,并实现 Comparable Interface 并将 CompareTo 方法重写为您自己的比较机制

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-12
    • 1970-01-01
    • 2012-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    相关资源
    最近更新 更多