【问题标题】:Sorting an Arraylist of strings on a portion of each string, delimited by a character在每个字符串的一部分上对字符串的 Arraylist 进行排序,由字符分隔
【发布时间】:2014-10-10 11:53:02
【问题描述】:

我正在尝试对strings 中的ArrayList 进行排序(不在int 中)。

鉴于: f.e.

[0] 23,24
[1] 12,33
[2] 37,11

Arraylist.Sort 应该回馈(按最后一个数字升序排序):

[0] 37,11
[1] 23,24
[2] 12,33

到目前为止:

public class Point
{
    public int i, j;

    public Point(int i, int j)
    {this.i = i; this.j = j;}

    public string ToString()
    {return i + "," + j;}
}

public class SList
{
    public static void Main()
    {
        ArrayList Slist = new ArrayList();
        Random Generate = new Random();
        for (int i = 0; i < 3; i++)
        {
            Point p = new Point(Generate.Next(40), Generate.Next(40));
            Slist.Add(p.ToString());
        }
        Slist.Sort();
    }
}

【问题讨论】:

  • 您能展示一下到目前为止您为实现这一目标所做的尝试吗?
  • 您使用非通用 ArrayList 而不是通用 List&lt;T&gt; 是否有原因?
  • 您尚未指定预期的排序方式
  • 您想使用字典顺序(x 在 y 之前)进行排序,对吗?为什么不让你的PointIComparable 和/或使用明显的Array.Sort 重载之一?
  • 如何使用IComparable 做到这一点?

标签: c# string sorting arraylist


【解决方案1】:

我不能 100% 确定您是否有一个字符串数组或者它们是否已经被拆分,但您可以创建一个自定义比较器并执行类似的操作。更清楚您想要什么,以便人们可以更好地帮助您。

    public class MyCustomComparer : IComparer<string>
    {
        public int Compare(string x, string y)
        {
            var xIntValues = x.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
            var yIntValues = y.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();

            for(var i = 0; i < Math.Min(xIntValues.Count(), yIntValues.Count()); ++i)
                if (xIntValues[i] != yIntValues[i])
                    return xIntValues[i] - yIntValues[i];
            return xIntValues.Count() - yIntValues.Count();
        }
    }

然后像这样使用它,你的数组元素包含像"37, 11"这样的字符串

    Array.Sort(myArray, MyCustomComparer);

【讨论】:

    【解决方案2】:

    在 c# 1.0 之后使用 ArrayList 有点奇怪,但如果您因为遗留原因而使用 ArrayList,您可以创建自己的非通用自定义比较器,如下所示:

    public class CustomComparer : IComparer<string>, IComparer {
    
        #region IComparer<string> Members
    
        int? ExtractNumber(string str)
        {
            int index = str.LastIndexOf(',');
            if (index < 0)
                return null;
            var subStr = str.Substring(index+1);
            int result;
            if (int.TryParse(subStr, out result))
                return result;
            return null;
        }
    
        // Return x - y
        public int Compare(string x, string y)
        {
    #if false
            Given: f.e.
            [0] 23,24
            [1] 12,33
            [2] 37,11
            Arraylist.Sort should give back (sorted by the last number ascending):
            [0] 37,11
            [1] 23,24
            [2] 12,33
    #endif
            var xVal = ExtractNumber(x);
            var yVal = ExtractNumber(y);
            if (!xVal.HasValue && !yVal.HasValue)
                return x.CompareTo(y);
            else if (!xVal.HasValue)
                return 1;
            else if (!yVal.HasValue)
                return -1;
            int cmp = xVal.Value.CompareTo(yVal.Value);
            if (cmp != 0)
                return cmp;
            return x.CompareTo(y);
        }
    
        #endregion
    
        #region IComparer Members
    
        public int Compare(object x, object y)
        {
            if (object.ReferenceEquals(x, y))
                return 0;
            string xStr = x as string;
            string yStr = y as string;
            if (xStr == null && yStr == null)
                return 0;  // NO IDEA
            else if (xStr == null)
                return 1;
            else if (yStr == null)
                return -1;
            else return Compare(xStr, yStr);
        }
    
        #endregion
    }
    

    【讨论】:

      【解决方案3】:

      以下代码在您的类上实现IComparable。它按升序对y 进行排序:

      public class Point : IComparable<Point>
      {
          public int x;
          public int y;
      
          public Point(int x, int y)
          {
              this.x = x;
              this.y = y;
          }
          public string ToString()
          {
              return x + "," + y;
          }
      
          public int CompareTo(Point other)
          {
               return this.y.CompareTo(other.y);
          }
      
      }
      

      您现在可以使用ArrayList.Sort() 来实现您需要的订单。

      【讨论】:

        【解决方案4】:

        最简单的方法是远离您的非通用列表:

        var sortedList = list.Cast<string>().OrderBy(x => x.Split(',')[1]);
        

        代码一目了然。

        使用这个作为输入:

        var list = new ArrayList();
        list.Add("23,24");
        list.Add("12,33");
        list.Add("37,11");
        

        将此作为输出:

        37,11
        23,24
        12,33

        【讨论】:

          猜你喜欢
          • 2020-02-20
          • 2014-02-21
          • 2023-02-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-14
          • 2013-05-22
          • 2011-12-30
          相关资源
          最近更新 更多