Linq OrderBy on generic list返回不完全按字母顺序排列的列表

时间:2012-11-16 21:12:40

标签: c# linq

我正在尝试使用Name属性对象对通用的对象列表进行排序。我正在使用LINQ,并且以下表达式不太起作用:

var query = possibleWords.OrderBy(x => x.Name.ToLower()).ToList();
foreach (Word word in query) //possibleWords.OrderBy(word => word.Name))
   {
            listWords.Items.Add(word.Name);
   }

“query”现在应该包含一个有序项目列表,如果我理解正确,并且项目应该添加到名为listWords的列表框中。

然而输出是这样的:

http://screencast.com/t/s1CkkWfXD4(对不起URL链接,但是SO已经以某种方式将我锁定在我的帐户之外,显然我无法使用这个新帐户发布图片。)

列表框几乎按字母顺序但不完整。出于某种原因,“aa”和“aaaa”排在最后。可能是什么原因,以及如何解决它?

提前致谢。

按要求详细说明

此代码在Visual Studio中输入并执行时:

        List<Word> words = new List<Word>();

        words.Add(new Word("a"));
        words.Add(new Word("Calculator"));
        words.Add(new Word("aaa"));
        words.Add(new Word("Projects"));
        words.Add(new Word("aa"));
        words.Add(new Word("bb"));
        words.Add(new Word("c"));

        IEnumerable<Word> query = words.OrderBy(x => x.Name.ToLower()).ToList();

        foreach (Word word in query)
        {
            Console.WriteLine(word.Name);
        }

给我以下输出:

a
bb
c
Calculator
ccc
Projects
aa
aaa

这没有正确排序:第一个“a”是正确的,但随后的“aa”和“aaa”条目被发送到列表的底部。

我对字符集和编码知之甚少,所以我可能会在这里犯一个菜鸟错误。但在那种情况下,我不认识那可能是什么,我会有点疑惑为什么第一个“a”正确排序,但第二个和第三个“aa”和“aaa”不是!

进一步阐述 - 词类

[Serializable()]
public class Word
{
    [System.Xml.Serialization.XmlAttribute("Name")]
    public string Name { get; set; }

    public Word(string name)
    {
        Name = name;
    }

    public Word() { } //Parameter less constructor neccessary for serialization

}

原因和解决方案

像@Douglas建议的那样,通过将StringComparer.InvariantCultureIgnoreCase比较器提供给OrderBy方法来解决问题。

在进一步的研究中,使用丹麦文化(da-DK)时,似乎FindAll和OrderBy方法(可能还有其他方法)都存在问题。可能有其他方法或文化失败,但da-DK文化和FindAll + OrderBy方法肯定没有按预期工作。

OrderBy方法存在此线程中描述的问题(错误排序)。 FindAll方法有一个类似的,非常奇怪的问题:假设我们有一个条目列表:a,aa,aaa和aaaa。当使用FindAll(x =&gt; x.StartsWith(“a”))时,它只返回“a”NOT aa,aaa和aaaa。如果使用StartsWith(“aa”),它将正确找到aa,以及aaa和aaaa。当使用StartWith(“aaa”)时,它将再次找不到aaaa,只有aaa!这似乎是框架中的一个错误。

3 个答案:

答案 0 :(得分:6)

你可以尝试更换:

IEnumerable<Word> query = words.OrderBy(x => x.Name.ToLower()).ToList();

...与:

IEnumerable<Word> query = words.OrderBy(x => x.Name, 
    StringComparer.InvariantCultureIgnoreCase);

这是一个非常小的机会,这是一个奇怪的文化问题。

答案 1 :(得分:5)

以下代码输出预期结果:

class Word
{
    public Word(string str)
    {
        Name = str;
    }

    public string Name { get; private set; }
}

public static void Main(string[] args)
{
    List<Word> words = new List<Word>();

    words.Add(new Word("a"));
    words.Add(new Word("Calculator"));
    words.Add(new Word("aaa"));
    words.Add(new Word("Projects"));
    words.Add(new Word("aa"));
    words.Add(new Word("bb"));
    words.Add(new Word("c"));

    IEnumerable<Word> query = words.OrderBy(x => x.Name.ToLower()).ToList();

    foreach (Word word in query)
    {
        Console.WriteLine(word.Name);
    }
}

输出:

a
aa
aaa
bb
c
Calculator
Projects

更新 的 好的,神秘解决了(有点)。 如果您在代码之前执行以下操作:

var cultureInfo = new CultureInfo("da-DK");
Thread.CurrentThread.CurrentCulture = cultureInfo;
Thread.CurrentThread.CurrentUICulture = cultureInfo;

你得到“不正确”的输出:

a
bb
c
Calculator
Projects
aa
aaa

显然丹麦词典比较的规则是不同的。 以下是我在网上找到的解释(http://stackoverflow.com/questions/4064633/string-comparison-in-java):

请注意,这非常依赖于活动区域设置。例如,在丹麦,我们有一个字符“å”,以前拼写为“aa”,与两个单独的a非常不同。因此,丹麦的排序规则将两个连续的a与“å”相同,这意味着它在z之后。这也意味着丹麦语词典的排序方式与英语或瑞典词典不同。

答案 2 :(得分:2)

最后一个“a”很可能是一些不同的(非ASCII)字符。检查字符代码(int)("a"[0]),看它是否与英语“a”相同。

如果是这样的话,排序没有错误 - 没有什么可以解决的(除了可能更好地理解你的数据)。