【问题标题】:Natural Sorting of list of string in descending order C#自然排序的字符串列表的降序C#
【发布时间】:2018-12-04 22:04:31
【问题描述】:

我想问一下如何使用Natural Sort Comparer 库对List<string> 进行降序排序。

我想问一下你是否有人使用过这个库 https://www.codeproject.com/Articles/22517/Natural-Sort-ComparerList<string>进行排序?

这是升序的代码sn-ps

public List<string> contents = new List<string>{ "a,b,c,d,e,f" };
public void sorting()
{
   using (NaturalSortComparer comparer = new NaturalSortComparer())
   {
      contents.Sort(comparer);
   }
}

我能够使其按升序排序,但不能降序

有什么想法吗?

【问题讨论】:

  • 调用它NaturalDescendingComparer 然后反转所有内容,例如将if(y1.Length &gt; x1.Length) 更改为if(y1.Length &lt; x1.Length)。在PartCompare 中,您需要恢复比较变量的顺序,例如:return y.CompareTo(x);
  • 我认为没有内置功能可以使排序降序。但是你可以实现一个比较器,让它做你需要的。

标签: c# sorting c#-4.0 libraries


【解决方案1】:

让我们实现一个简单的扩展方法

  public static partial class ComparerExtensions {
    public static IComparer<T> Reverse<T>(this IComparer<T> comparer) {
      if (null == comparer)
        throw new ArgumentNullException(nameof(comparer));

      return Comparer<T>.Create((left, right) => comparer.Compare(right, left));
    }
  }

然后你可以反转任何你喜欢的比较器(ICompare&lt;T&gt;):

 MyList.Sort(YourCustomComparer.Reverse());

在你的情况下(比较器实现IDisposable有点奇怪):

 using (var naturalComparer = new NaturalComparer()) {
   contents.Sort(naturalComparer.Reverse()); 
 }

编辑:如果是C# 4.0或更早的版本(没有Comparer&lt;T&gt;.Create),我们可以像这样实现扩展方法:

  public static partial class ComparerExtensions {
    private sealed class ReversedComparer<T> : IComparer<T> {
      private readonly IComparer<T> m_Comparer;

      public ReversedComparer(IComparer<T> comparer) {
        m_Comparer = comparer;
      }

      public int Compare(T x, T y) {
        return m_Comparer.Compare(y, x);
      }
    }

    public static IComparer<T> Reverse<T>(this IComparer<T> comparer) {
      if (null == comparer)
        throw new ArgumentNullException(nameof(comparer));

      return new ReversedComparer<T>(comparer);
    }
  }

【讨论】:

  • Sort 排序 inplaceOrderByDescendingLinq 扩展)不排序。因此我们必须添加 ToList 这会带来开销:MyList = MyList.OrderByDescending(...).ToList(); disposing NaturalComparer 的另一个问题
  • 我认为最简洁的方法是简单地切换CompareTo中的参数顺序。
  • @InBetween:谢谢!我瞎了眼!
  • 嗨 Dmitry,我尝试执行您的建议,但编译器告诉我 Create 不是 Comparer&lt;T&gt; 的定义
  • @Hikari: 请问您使用的c# version 是什么?是 4.0 还是更低? stackoverflow.com/questions/32901435/comparert-create-in-net-4
【解决方案2】:

你有两个选择:

  1. 太糟糕了,永远不要这样做:使用升序,然后简单地调用 Reverse() 方法(我只是将此选项列为警告,因为不管你信不信,我已经看到了不止一次在生产代码中)。
  2. 好方法:实现一个IComparer&lt;string&gt;,它只返回“升序”比较器的负数(或切换参数顺序)并将其传递给您的排序方法。

但是 nº2 已经为您构建在框架中;它的扩展方法OrderByDescending:

var ss = new[] {"a1", "a03", ... }
var descending = ss.OrderByDescending(
    s => s,
    new NaturalComparer());

更新:您更新的问题似乎暗示您想使用List.Sort。在这种情况下,要走的路是#2,OrderBy 不会就地排序。

【讨论】:

  • 由于contents.Sort(comparer);排序就地看来你必须添加.ToList():contents = contents.OrderBy(...).ToList();
  • @DmitryBychenko 啊...您必须使用 Sort 的要求最初并不存在。那么选项 nº2 仍然有效。
  • NaturalComparer 类实现了IDisposable(是的,这是一个非常奇怪的实现)。它应该放置在哪里
  • @DmitryBychenko 忘记处理问题,它不需要被处理......让我觉得为什么作者决定这必须是IDisposable;很确定他并不真正了解内存管理的工作原理。
  • 我注意到技术上实现一个简单地交换底层IComparer符号的IComparer是不正确的,因为0x80000000是一个合法的输出比较,但不能肯定。正确的解决方案是创建一个 IComparer,如果包装比较器返回 0,则返回 0,如果返回负数,则返回 1,如果返回正数,则返回 -1。或者,正如您所注意到的,交换参数的顺序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-03
  • 1970-01-01
  • 2020-06-28
  • 1970-01-01
  • 1970-01-01
  • 2014-04-11
相关资源
最近更新 更多