按字母顺序排序一个列表

107

我有以下类:

class Detail
{
    public Detail()
    {
        _details = new List<string>();
    }
    public IList<string> Details { get { return _details; } }
    private readonly List<string> _details;
}

目前我使用以下方法随机排序类:

void ShuffleGenericList<T>(IList<T> list)
{
    //generate a Random instance
    var rnd = new Random();
    //get the count of items in the list
    var i = list.Count();
    //do we have a reference type or a value type
    T val = default(T);

    //we will loop through the list backwards
    while (i >= 1)
    {
        //decrement our counter
        i--;
        //grab the next random item from the list
        var nextIndex = rnd.Next(i, list.Count());
        val = list[nextIndex];
        //start swapping values
        list[nextIndex] = list[i];
        list[i] = val;
    }
}

我希望做的是按字母顺序对详细内容进行排序。
例如,如果内容如下:
[0] a
[1] d
[2] b

我希望能够运行此方法并将它们排序为:

[0] a
[1] b
[2] d

有人知道如何简单地实现这个吗?请注意,列表通常只有不到十个条目。我可以用LINQ来做吗?抱歉,我对LINQ并不是很熟悉,我只是听说可以用它。

5个回答

184

您可以通过调用List<T>.Sort来就地对列表进行排序:

list.Sort();

这将使用元素的自然排序,对于你的情况来说是可以的。

编辑:请注意,在你的代码中,你需要

_details.Sort();

由于Sort方法只在List<T>中定义,而不是在IList<T>中定义。如果你需要从外部对其进行排序,而你又无法将其转换为List<T>(因为List<T>部分是实现细节),那么你就需要做更多的工作。

我不知道.NET中是否有基于IList<T>的原地排序,这有点奇怪。IList<T>提供了所有你需要的东西,所以它可以被编写成扩展方法。如果你想使用快速排序算法之类的东西,那么还有很多实现可用。

如果你不在意一点低效率,你总是可以使用:

public void Sort<T>(IList<T> list)
{
    List<T> tmp = new List<T>(list);
    tmp.Sort();
    for (int i = 0; i < tmp.Count; i++)
    {
        list[i] = tmp[i];
    }
}

换句话说,先复制,进行原地排序,然后再将排序后的列表复制回来。


您可以使用LINQ创建一个列表,其中包含原始值但已排序:

var sortedList = list.OrderBy(x => x).ToList();
这取决于您想要的行为。请注意,您的洗牌方法并不是理想的:
  • 在方法内创建一个新的Random会遇到一些问题
  • 您可以在循环中声明val - 您没有使用那个默认值
  • 在您知道自己正在使用IList<T>时,使用Count属性更加习惯用语
  • 在我的看法中,使用for循环比使用while循环反向遍历列表更加简单易懂
Stack Overflow上还有其他实现Fisher-Yates洗牌算法的例子-搜索一下您很快就能找到。

那么,如果我想对上面创建的列表进行排序,我只需要说:sortedList.Sort吗? - Mariko
我尝试了排序但无法使其工作。我的列表看起来像这样:IList<string> nD。我尝试了nD.Sort(),但它显示:无法解析符号“Sort”。 - Mariko
@Mariko:使用_details.Sort()代替 - 因为_details被声明为List<string>而不是IList<string>Sort仅在List<T>上声明,而不是在IList<T>上声明。 - Jon Skeet

35

有两种方法:

不使用LINQ:yourList.Sort();

使用LINQ:yourList.OrderBy(x => x).ToList()

您可以在此处找到更多信息:https://www.dotnetperls.com/sort


@Dminox - 我的列表看起来像这样:IList<string> nD。我尝试了 nD.Sort() 但它显示:“无法解决符号'Sort'”。 - Mariko
1
@Mariko Sort()List<T> 的成员方法,不是 IList<T> 的成员方法。如果您预计要使用不同的 IList<T> 实现,请考虑转换为前者。 - dlev

28

另外一种方式

_details.Sort((s1, s2) => s1.CompareTo(s2)); 

10
这个方法的优势在于可以适应通过其属性之一对任何对象进行排序。 - MGOwen
+1 我将这个答案与另一个答案结合起来,用于对字符串的排序顺序进行单元/集成测试。 - computercarguy

13

您应该能够在LINQ中使用OrderBy...

var sortedItems = myList.OrderBy(s => s);

2
注意:返回的是 IEnumerable<T>,不是原地排序。 - abatishchev

1

@goril - 我想使用这个,但是出现了错误。这是我添加到另一个评论中的内容。希望你能帮忙 - 我的列表看起来像这样:IList<string> nD。我尝试了nD.Sort(),但它显示:无法解析符号“Sort”。 - Mariko
1
@Mariko:你使用的接口IList<T>中并没有包含Sort方法。直接对List<T>变量进行排序。换句话说,你可以对你的例子中的_details进行排序,但不能对Details进行排序。 - Oleg Dudnyk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接