我正在尝试使用对象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);
}
Run Code Online (Sandbox Code Playgroud)
"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);
}
Run Code Online (Sandbox Code Playgroud)
给我以下输出:
a
bb
c
Calculator
ccc
Projects
aa
aaa
Run Code Online (Sandbox Code Playgroud)
这没有正确排序:第一个"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
}
Run Code Online (Sandbox Code Playgroud)
原因和解决方案
像@Douglas建议的那样,通过将StringComparer.InvariantCultureIgnoreCase比较器提供给OrderBy方法来解决问题.
在进一步的研究中,当使用丹麦文化(da-DK)时,似乎FindAll和OrderBy方法(可能是其他方法)都存在问题.可能有其他方法或文化失败,但da-DK文化和FindAll + OrderBy方法肯定没有按预期工作.
OrderBy方法存在此线程中描述的问题(错误排序).FindAll方法有一个类似的,非常奇怪的问题:假设我们有一个条目列表:a,aa,aaa和aaaa.当使用FindAll(x => x.StartsWith("a"))时,它只返回"a"NOT aa,aaa和aaaa.如果使用StartsWith("aa"),它将正确找到aa,以及aaa和aaaa.当使用StartWith("aaa")时,它将再次找不到aaaa,只有aaa!这似乎是框架中的一个错误.
你能尝试更换:
IEnumerable<Word> query = words.OrderBy(x => x.Name.ToLower()).ToList();
Run Code Online (Sandbox Code Playgroud)
...有:
IEnumerable<Word> query = words.OrderBy(x => x.Name,
StringComparer.InvariantCultureIgnoreCase);
Run Code Online (Sandbox Code Playgroud)
这是一个奇怪的文化问题的可能性非常小.
以下代码输出预期结果:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
a
aa
aaa
bb
c
Calculator
Projects
Run Code Online (Sandbox Code Playgroud)
更新: 好的,神秘解决了(有点).如果在代码之前执行以下操作:
var cultureInfo = new CultureInfo("da-DK");
Thread.CurrentThread.CurrentCulture = cultureInfo;
Thread.CurrentThread.CurrentUICulture = cultureInfo;
Run Code Online (Sandbox Code Playgroud)
你得到"不正确"的输出:
a
bb
c
Calculator
Projects
aa
aaa
Run Code Online (Sandbox Code Playgroud)
显然丹麦词典比较的规则是不同的.以下是我在网上找到的解释(http://stackoverflow.com/questions/4064633/string-comparison-in-java):
请注意,这非常依赖于活动区域设置.例如,在丹麦,我们有一个字符"å",它曾经拼写为"aa",与两个单独的a非常不同.因此,丹麦的排序规则将两个连续的a与"å"相同,这意味着它在z之后.这也意味着丹麦语词典的排序方式与英语或瑞典词典的排序方式不同.