7

我正在尝试使用 objects 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);
   }

如果我理解正确,“查询”现在应该包含一个有序项目的列表,并且项目应该添加到名为 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”却不是!

进一步阐述 - Word 类

[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 => x.StartsWith("a")) 时,它只会返回 "a" 而不是 aa、aaa 和 aaaa。如果使用 StartsWith("aa"),它将正确找到 aa,以及 aaa 和 aaaa。使用 StartWith("aaa") 时,它将再次找不到 aaaa,只有 aaa!这似乎是框架中的一个错误。

4

3 回答 3

6

Could you try replacing:

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

…with:

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

There's a very small chance that it's a weird culture issue.

于 2012-11-16T22:09:31.277 回答
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 之后。这也意味着丹麦语词典的排序方式与英语或瑞典语词典不同。

于 2012-11-16T21:48:35.873 回答
2

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

如果是这种情况,排序并没有什么问题 - 没有什么可修复的(除了可能更好地理解您的数据)。

于 2012-11-16T21:19:37.527 回答