我正在尝试使用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!这似乎是框架中的一个错误。
答案 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”相同。
如果是这样的话,排序没有错误 - 没有什么可以解决的(除了可能更好地理解你的数据)。