列出“按订单”故障

时间:2013-01-29 15:31:13

标签: .net string

我有一个类似于学生坐的课程。 我的位置像B6 B7 B8 B9 B10 B11 如果我在某个类(一个oops版本)中使用FindAll,我会按此顺序获取它 一切顺利,直到我做

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

之后,该位置变为B10 B11 B6 B7 B8 B9 这里出了什么问题。我没有使用orderBY更好,但任何人都可以告诉我我遇到问题的原因吗?

8 个答案:

答案 0 :(得分: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());

答案 1 :(得分:3)

这是因为字符串被比较为......好吧,字符串。 '1'小于'6',因此词法比较将停止在该字符处。

听起来你想要一个natural sort而不是一个词汇排序。

答案 2 :(得分: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的类型为Location。然后您的原始sorted = someclass.OrderBy(r => r.location);将有效。

这两种解决方案都只是草图。我想你会想要添加一些健全性检查。

答案 3 :(得分:2)

按顺序排序,而不是数字排序。

'B10' < 'B6'

逐个字符地比较每个条目:

'B10'
'B6'
  ^

这是重要的角色(因为B是相同的)。 '6'&gt; '1'。

答案 4 :(得分:1)

orderby工作正常,请注意字符串B10出现在字符串B11之前,而字符串B11又出现在B6之前

请注意,您正在尝试订购List<string>(或者我认为的那样),而不是List<int>

答案 5 :(得分:1)

为了在按字典顺序排序的字符串中呈现数字,需要对它们进行填充,即B01&lt; B06&lt; B10为B6> B10从左到右完成。所以,如果你知道你的上界,你的简单选择是填充,否则你将不得不重新考虑一下。

答案 6 :(得分:0)

它们总是以“X ###”的形式存在吗?如果是这样,你可以使用:

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

这是一个解决方法。如果情况要复杂得多,那么您还需要为新创建的Location类创建一个比较器对象。

答案 7 :(得分:0)

您需要一种自然排序算法。取this one from Ian并将其调用:

someclass.OrderBy(r => r.location, new EnumerableComparer<String>());