2

私は学生が座っているようなクラスを持っています。私はB6 B7 B8 B9 B10 B11のような場所を持っています.FindAllをいくつかのクラス(1つのおっとバージョン)で使用すると、この順序で取得されます.

    someclass.OrderBy(r => r.location);

その後、場所は B10 B11 B6 B7 B8 B9 になり、ここで何が問題になっていますか。その場合、orderBYを使用しないほうがよいのですが、問題の理由を教えてもらえますか?

4

8 に答える 8

4

独自のカスタム比較子を実装できます...

class CustomCompare : IComparer<string>
{
    private static readonly char[] _digits = "0123456789".ToArray();

    public int Compare(string a, string b)
    {
        //assuming alpha start, numeric end
        var alphaA = a.TrimEnd(_digits);
        var alphaB = b.TrimEnd(_digits);
        var alphaCompareTo = alphaA.CompareTo(alphaB);

        if (alphaCompareTo != 0)
        {
            return alphaCompareTo;
        }

        var numericA = int.Parse(a.Substring(alphaA.Length));
        var numericB = int.Parse(b.Substring(alphaB.Length));

        return numericA.CompareTo(numericB);
    }
}

...そして、そのように使用します...

someclass.OrderBy(r => r.location, new CustomCompare());
于 2013-01-29T15:44:34.580 に答える
3

これは、文字列が文字列として比較されているためです。 '1'がより小さい'6'ため、字句比較はその文字で停止します。

字句ソートではなく自然ソートが必要なようです。

于 2013-01-29T15:33:41.167 に答える
3

あなたのlocationプロパティ(またはフィールド)は文字列だと思いますか?

次のように書くこともできますComparer<>

sealed class LocationComparer : Comparer<string>
{
  // expect strings like "B3" or "C26"
  public override int Compare(string x, string y)
  {
    int result = x[0].CompareTo(y[0]);
    if (result != 0)
      return result;
    result = ushort.Parse(x.Substring(1)).CompareTo(ushort.Parse(y.Substring(1)));
    return result;
  }
}

のように使いますsorted = someclass.OrderBy(r => r.location, new LocationComparer());

またはlocation、タイプを次のスタイルのクラスに変更できます。

// this class inherits the IComparable implementation of Tuple`2
sealed class Location : Tuple<char, ushort>
{
  public Location(char letter, ushort number)
    : base(char.ToUpper(letter), number)
  {
  }

  public Location(string locationString)
    : this(letter: locationString[0], number: ushort.Parse(locationString.Substring(1)))
  {
  }

  public override string ToString()
  {
    return Item1.ToString() + Item2.ToString();
  }
}

Someclassクラス内にlocationは type がありLocationます。その後、オリジナルsorted = someclass.OrderBy(r => r.location);が機能します。

どちらのソリューションも単なるスケッチです。いくつかのサニティチェックを追加したいと思うでしょう。

于 2013-01-29T16:05:22.097 に答える
2

Order by は、数値順ではなく文字列順を使用します。

'B10' < 'B6'

各エントリは、文字ごとに比較されます。

'B10'
'B6'
  ^

これが重要な文字です (B も同じです)。'6' > '1'.

于 2013-01-29T15:32:57.283 に答える
1

orderbyは正しく機能しています。文字列B10が文字列B11の前にあり、文字列B11がB6の前にあることに注意してください。

あなたが注文しようとしているList<string>のではなく(またはそれが私が思うものです)、List<int>

于 2013-01-29T15:33:51.103 に答える
1

In order to render numbers in strings lexicographically sortable, they'd need to be padded i.e. B01 < B06 < B10 as B6 is > B10 as it's done left to right. So your simple option is to pad if you know your upper bounds, otherwise you'll have to rethink a little.

于 2013-01-29T15:35:14.140 に答える
0

それらは常に「X###」の形式になりますか?もしそうなら、あなたは使うことができます:

yourListObject.OrderBy(r => int.Parse(r.location.SubString(1)));

これは1つの回避策です。状況がはるかに複雑な場合は、新しく作成されたLocationクラスの比較オブジェクトも作成する必要があります。

于 2013-01-29T15:42:58.870 に答える
0

自然な並べ替えアルゴリズムが必要です。Ian からこれを取得して、次のように呼び出します。

someclass.OrderBy(r => r.location, new EnumerableComparer<String>());
于 2013-01-29T15:46:26.897 に答える