如何对 IEnumerable<string> 进行排序
Posted
技术标签:
【中文标题】如何对 IEnumerable<string> 进行排序【英文标题】:How to sort an IEnumerable<string> 【发布时间】:2011-04-07 12:55:12 【问题描述】:如何按字母顺序对IEnumerable<string>
进行排序。这可能吗?
编辑:我将如何编写就地解决方案?
【问题讨论】:
【参考方案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
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<T>
。 IOrderedEnumerable<T>
派生自 IEnumerable<T>
,因此它可以像 IEnumerable<T>
一样使用,但它扩展了类型,例如,允许使用 ThenBy
。【参考方案2】:
这是不可能的,但事实并非如此。
基本上,任何排序方法都会将您的IEnumerable
复制到List
,对List
进行排序,然后将排序后的列表返回给您,即IEnumerable
和IList
。
这意味着您失去了 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);
【讨论】:
我不确定我是否会推荐这个。如果您有一个 IEnumerablelistToSort = (src is List<T>) ? (List<T>)src : new List<T>(src);
中的double casting anti pattern 呢?有没有像listToSort = (src as List<T>); if (null == listToSort) listToSort = new List<T>(src);
@JeroenWiertPluimers 示例代码也总是存在问题;也许我只是没有打扰,因为上面的内容略短,我想专注于手头的事情,但即使在示例中也能阻止坏习惯。以上是关于如何对 IEnumerable<string> 进行排序的主要内容,如果未能解决你的问题,请参考以下文章
如何获取枚举值属性的 IEnumerable<string>?
如何在 C# 中使用 Ienumerable 反转一系列元素?