8

私はここにこの質問への答えを追加しました:自然なソート順を必要とするC#でのソートList<String>、埋め込まれた数値を処理するもの。

しかし、私の実装は素朴であり、アプリケーションが物事を想定してUnicodeを正しく処理しない方法に関するすべての投稿の代わりに(トルコは誰かをテストしますか?)、より良い実装を書くための助けを求めたいと思いました。または、.NETの組み込みメソッドがある場合は、教えてください:)

その質問の答えの私の実装は、文字列を調べて、文字ごとに比較し、両方の数字に遭遇するまで続けます。次に、両方の文字列から連続する数字を抽出します。これにより、長さが変化する可能性があり、最短のものに先行ゼロを埋めてから、比較します。

ただし、問題があります。

たとえば、文字列xに2つのコードポイントがあり、それらが一緒になって文字Èを作成しているのに、もう1つの文字列には、その文字であるコードポイントが1つしかない場合はどうでしょうか。

私のアルゴリズムは、発音区別符号を1文字として扱い、他の文字列のÈと比較するため、これらのアルゴリズムでは失敗します。

誰かがこれを適切に処理する方法を教えてもらえますか?CultureInfoドイツの「ss」と「ß」の比較など、言語の問題を処理するオブジェクトを指定するためのサポートが必要です。

個々のコードポイントではなく、「実際の文字」(ここでは実際の用語はわかりません)を列挙するようにコードを取得する必要があると思います。

これに対する正しいアプローチは何ですか?

また、「自然」が「人間が期待する方法」を意味する場合、私は次のことを熟考するために追加します。

  • 日時はどうですか?
  • 浮動小数点値はどうですか?
  • 「自然」と見なされる他のシーケンスはありますか?
    • これをどこまで伸ばす必要がありますか?(Eeny、meeny、miny、moe)
4

2 に答える 2

8

これはすでにWindowsで利用可能であり、シェルはエクスプローラーウィンドウでファイルを配置するときに自然順を使用します。使用する比較関数は、少なくともWindows 2000以降、すべてのプログラムにエクスポートされて使用できます。P/ Invokeは最高のソリューションではありませんが、過去10年間に何十億回もテストされているという大きな利点があります。そして、ユーザーがすでによく知っている方法で文字列をソートします。

発音区別符号の処理はすでに.NETの一部であり、string.Normalize()メソッドがそれを処理します。

これを使用するサンプルプログラムは次のとおりです。元のスレッドで要求されたとおりに文字列を適切に並べ替えます。

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

class Program {
    static void Main(string[] args) {
        string[] arr = new string[] { "1", "5", "3", "6", "11", "9", "NUM1", "NUM0" };
        Array.Sort(arr, new LogicalComparer());
        foreach (string s in arr) Console.WriteLine(s);
        Console.ReadLine();
    }
}
class LogicalComparer : IComparer<string> {
    public int Compare(string x, string y) {
        return StrCmpLogicalW(x.Normalize(), y.Normalize());
    }
    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
    private static extern int StrCmpLogicalW(string s1, string s2);
}
于 2010-09-15T13:12:50.877 に答える
2

.NETについてはよくわかりませんが、アルゴリズムの質問でもあるため、ここに2セントを示します。

おそらく正規表現を使用して、文字列をトークンに分割しようとします。次に、トークンのタイプに応じて適切な比較関数を使用して、文字列をトークンごとに比較できます。

すなわち:

  1. 日付、数字、単語などの正規表現を定義します。これらの最後の式は、任意の文字に一致するフォールバック式である必要があります。
  2. 両方の文字列の先頭で一致するまで、各式を最初に具体的に試してください
  3. 一致する部分を抽出し、適切な比較機能を使用して比較します。
  4. 等しい場合は、両方の文字列の先頭から一致を削除し、手順2から繰り返します。

[a-zA-Z]正規表現を使用すると、.のような適切な文字クラスを使用しない場合は、Unicodeをサポートすることも可能になるはずです[:alpha:]

さまざまな形式のÈの比較については、最初に文字列の正規化を試みることができます。

于 2010-09-15T12:01:28.023 に答える