【问题标题】:How to sort an IEnumerable<string>如何对 IEnumerable<string> 进行排序
【发布时间】:2011-04-07 12:55:12
【问题描述】:

如何按字母顺序对IEnumerable&lt;string&gt; 进行排序。这可能吗?

编辑:我将如何编写就地解决方案?

【问题讨论】:

    标签: c# .net string sorting ienumerable


    【解决方案1】:

    与您对任何其他可枚举的排序方式相同:

    var result = myEnumerable.OrderBy(s => s);
    

    var result = from s in myEnumerable
                 orderby s
                 select s;
    

    或(忽略大小写)

    var result = myEnumerable.OrderBy(s => s,
                                      StringComparer.CurrentCultureIgnoreCase);
    

    请注意,与 LINQ 一样,这会创建一个新的 IEnumerable,在枚举时,它会按排序顺序返回原始 IEnumerable 的元素。它不会就地对 IEnumerable 进行排序。


    IEnumerable 是只读的,即只能从中检索元素,而不能直接修改。如果要对字符串集合进行就地排序,则需要对实现了 IEnumerable 的原始集合进行排序,或者先将 IEnumerable 变成可排序的集合:

    List<string> myList = myEnumerable.ToList();
    myList.Sort();
    

    根据您的评论:

    _components = (from c in xml.Descendants("component")
                   let value = (string)c
                   orderby value
                   select value
                  )
                  .Distinct()
                  .ToList();
    

    _components = xml.Descendants("component")
                     .Select(c => (string)c)
                     .Distinct()
                     .OrderBy(v => v)
                     .ToList();
    

    或(如果您想稍后将更多项目添加到列表中并保持排序)

    _components = xml.Descendants("component")
                     .Select(c => (string)c)
                     .Distinct()
                     .ToList();
    
    _components.Add("foo");
    _components.Sort();
    

    【讨论】:

    • 或 myEnumerable.OrderByDescending(s => s)。
    • 所以,_components = _components.OrderBy(s => s);会好吗?
    • @CatZilla:应该可以,但可能不是解决实际问题的最佳方法。 _components是什么,从哪里获取,如何使用?
    • @dtb:哦,_components 正是通过这种方式从 XML 文件中填充的:_components = (from c in xml.Descendants("component") select c.Value.ToString()).Distinct( ).ToList();我需要对其进行排序。
    • OrderBy 返回IOrderedEnumerable&lt;T&gt;IOrderedEnumerable&lt;T&gt; 派生自 IEnumerable&lt;T&gt;,因此它可以像 IEnumerable&lt;T&gt; 一样使用,但它扩展了类型,例如,允许使用 ThenBy
    【解决方案2】:

    这是不可能的,但事实并非如此。

    基本上,任何排序方法都会将您的IEnumerable 复制到List,对List 进行排序,然后将排序后的列表返回给您,即IEnumerableIList

    这意味着您失去了 IEnumerable 的“无限继续”属性,但无论如何您都无法对它进行排序。

    【讨论】:

    • 正确。 IEnumerable 的目的是为您提供一个系列的句柄,您可以通过继续询问“下一个”项目来从头到尾进行迭代。这意味着一个 IEnumerable 可以在所有内容已知之前进行部分迭代;你不必知道什么时候你已经完成了所有这些,直到你完成了。排序(就像 Linq 让你做的许多事情一样)需要将整个系列作为有序列表的知识;排序后的系列中最先出现的项目可能是系列返回的最后一个,除非您知道所有项目是什么,否则您不会知道这一点。
    【解决方案3】:
    myEnumerable = myEnumerable.OrderBy(s => s);
    

    【讨论】:

      【解决方案4】:

      我们不能总是在原地进行,但我们会检测何时可能:

      IEnumerable<T> SortInPlaceIfCan(IEnumerable<T> src, IComparer<T> cmp)
      {
        List<T> listToSort = (src is List<T>) ? (List<T>)src : new List<T>(src);
        listToSort.Sort(cmp);
        return listToSort;
      }
      IEnumerable<T> SortInPlaceIfCan(IEnumerable<T> src, Comparison<T> cmp)
      {
        return SortInPlaceIfCan(src, new FuncComparer<T>(cmp));
      }
      IEnumerable<T> SortInPlaceIfCan(IEnumerable<T> src)
      {
        return SortInPlaceIfCan(src, Comparer<T>.Default);
      }
      

      这使用了以下方便的结构:

      internal struct FuncComparer<T> : IComparer<T>
      {
        private readonly Comparison<T> _cmp;
        public FuncComparer(Comparison<T> cmp)
        {
            _cmp = cmp;
        }
        public int Compare(T x, T y)
        {
            return _cmp(x, y);
        }
      }
      

      【讨论】:

      • 我不确定我是否会推荐这个。如果您有一个 IEnumerable 但不知道实现的实际类型,您可能不应该修改它。顺便说一句,Array.FunctorComparer 是内部的。
      • 在修改我们所拥有的内容时,我认为这暗示在寻找就地的问题中;它暗示了它。在方法名称中包含“InPlaceInCan”是一个原因;方法名称比最好的文档更能提前说明风险;)是的,Array.FunctorComparer 是内部的,但它是微不足道的。我把它放进去是因为这是我能想到的最好的方式,例如“你的函子比较器在你的首选助手类中”。
      • @dtb 重新考虑,改为使用我自己的(再次查看 Array.FunctorComparer,无论如何我更喜欢我的!)
      • 聪明的想法和命名!但是为什么listToSort = (src is List&lt;T&gt;) ? (List&lt;T&gt;)src : new List&lt;T&gt;(src); 中的double casting anti pattern 呢?有没有像listToSort = (src as List&lt;T&gt;); if (null == listToSort) listToSort = new List&lt;T&gt;(src);
      • @JeroenWiertPluimers 示例代码也总是存在问题;也许我只是没有打扰,因为上面的内容略短,我想专注于手头的事情,但即使在示例中也能阻止坏习惯。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-20
      • 1970-01-01
      • 1970-01-01
      • 2014-10-14
      • 2016-08-28
      • 2017-11-02
      相关资源
      最近更新 更多