7

オブジェクトの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」が正しく順序付けられている理由について少し戸惑うでしょうが、2番目と3番目の「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 => x.StartsWith( "a"))を使用すると、aa、aaa、およびaaaaではなく"a"のみが返されます。StartsWith( "aa")を使用すると、aaaとaaaaだけでなく、aaも正しく検出されます。StartWith( "aaa")を使用すると、再びaaaaは検出されず、aaaのみが検出されます。これはフレームワークのバグのようです。

4

3 に答える 3

6

交換してみてください:

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

…と:

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

それが奇妙な文化の問題である可能性はごくわずかです。

于 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」と綴られていた文字「å」があり、2つのシングルaとは非常に異なります。したがって、デンマーク語の並べ替え規則では、2つの連続するaが「å」と同じように扱われます。これは、zの後に続くことを意味します。これは、デンマーク語の辞書が英語やスウェーデン語の辞書とは異なる方法でソートされていることも意味します。

于 2012-11-16T21:48:35.873 に答える
2

ほとんどの場合、最後の「a」は別の(ASCII以外の)文字です。文字コード(int)("a"[0])をチェックして、英語の「a」と同じかどうかを確認します。

その場合、並べ替えに問題はありません。修正する必要はありません(データをよりよく理解することを除いて)。

于 2012-11-16T21:19:37.527 に答える