2

ここから借用したコードを使用して、アプリケーションでカスタム オブジェクトのコレクションを整理しようとしています。通常、次の文字列に遭遇するまで、並べ替えは正常に機能します

D-016.0,
D-016.,
D-016.00,
D-016.000 001,
D-016.000 002,
D-016.000,
D-016.00 003,
D-016.00 002,
D-016. 001,
D-016. 002,
D-016.0 001,
D-016.00 001

非常に奇妙な理由で、コレクションを順番に返します

D-016.00,
D-016.000,
D-016.0,
D-016.000 001,
D-016. 001,
D-016.0 001,
D-016.00 001,
D-016.00 002,
D-016.000 002,
D-016. 002,
D-016.00 003,
D-016.

私が期待しているコレクションは、Windows エクスプローラーが表示するはずのコレクションのように見えます。

D-016. 001,
D-016. 002,
D-016.,
D-016.000 001,
D-016.000 002,
D-016.000,
D-016.00 001,
D-016.00 002,
D-016.00 003,
D-016.00,
D-016.0 001,
D-016.0,

Michael Kniskern によって投稿された C# の Natural Sort Orderからの提案に従って、shlwapi.dll を使用する回答を実装しようとしましたが、これは、上記の最後のコレクションに従って、ii が期待する順序を返します。ただし、このアプローチは Windows 7 でのみ機能し、Windows XP では不均一なコレクションを返します。

D-016.00、D-016.0、および D-016.000 としてリストされているファイルは、int に解析するときに連結された 0 のリストを取得し、このエラーが発生すると思われます。ただし、これを正確に修正する方法を正確に理解することはできません(これらの比較インターフェイスには新しすぎます)。誰でもこれに対する解決策を提案できますか?

以下は私が現在使用しているコードです

public class NaturalSorter<T> : IComparer<string>, IDisposable
{
    private readonly bool ascending;
    private Dictionary<string, string[]> table = new Dictionary<string, string[]>();


    public NaturalSorter(bool inAscendingOrder = true)
    {
        ascending = inAscendingOrder;
    }

    #region IComparer Members


    public int Compare(string[] x, string[] y)
    {
        throw new NotImplementedException();
    }

    #endregion

    #region IComparer Members

    int IComparer<string>.Compare(string x, string y)
    {
        if (x == y)
            return 0;

        string[] x1, y1;

        if (!table.TryGetValue(x, out x1))
        {
            x1 = Regex.Split(x.Replace(" ", ""), "([0-9]+)");
            table.Add(x, x1);
        }

        if (!table.TryGetValue(y, out y1))
        {
            y1 = Regex.Split(y.Replace(" ", ""), "([0-9]+)");
            table.Add(y, y1);
        }

        int returnVal = 0;

        for (int i = 0; i < x1.Length && i < y1.Length; i++)
        {
            if (x1[i] != y1[i])
            {
                returnVal = PartCompare(x1[i], y1[i]);
                return ascending ? returnVal : -returnVal;
            }
        }

        if (y1.Length > x1.Length)
        {
            returnVal = 1;
        }
        else if (x1.Length > y1.Length)
        {
            returnVal = -1;
        }
        else
        {
            returnVal = 0;
        }

        return ascending ? returnVal : -returnVal;
    }

    private static int PartCompare(string left, string right)
    {
        int x, y;
        if (!int.TryParse(left, out x))
            return left.CompareTo(right);

        if (!int.TryParse(right, out y))
            return left.CompareTo(right);

        return x.CompareTo(y);
    }

    #endregion

    public void Dispose()
    {
        table.Clear();
        table = null;
    }
}
4

1 に答える 1

0

これは私が思いつくことができる最高のものです:

分割を次のように置き換えます。

if (!table.TryGetValue(x, out x1))
{
    x1 = Regex.Split(x, @"([0-9]+|\.)");
    table.Add(x, x1);
}

if (!table.TryGetValue(y, out y1))
{
    y1 = Regex.Split(y, @"([0-9]+|\.)");
    table.Add(y, y1);
}

そして、以下を先頭に追加します PartCompare()

private static int PartCompare(string left, string right)
{
     if (left.Length > right.Length) return -1;
     else if (left.Length < right.Length) return 1;

     int x, y;
     ...

これにより、次が生成されます。

D-016. 001,
D-016. 002,
D-016.000 001,
D-016.000 002,
D-016.000,
D-016.00 001,
D-016.00 002,
D-016.00 003,
D-016.00,
D-016.0 001,
D-016.0,
D-016.,  // The one out-of-order item.
于 2013-01-29T16:55:45.987 に答える