2011-04-03 42 views
1

我有一个ArrayList字符串,看起来如下,我想输出一个新的ArrayList排序在一个特定的方式。但不确定排序的好方法。帮助将非常感激!C# - 排序字符串ArrayList

原件(可以是任何随机顺序):

1:1 
0:0 
0:1 
2:1 
1:0 
2:0 

输出:

2:0 
2:1 
1:0 
1:1 
0:0 
0:1 
+0

@Mike - 有没有可能来存储信息的对象,而不是字符串?即他们需要是字符串,还是只有当他们输出? – Pandincus 2011-04-03 02:50:39

+0

@Pandincus:我想再次输出它们作为排序的字符串。但是,如果这使得它更容易,我想这会很好。 – 2011-04-03 02:53:40

+0

@Mike - 另外,你使用的是什么版本的.NET Framework? – Pandincus 2011-04-03 02:56:21

回答

1

虽然我认为其他答案都是现成的,但我会假设您不熟悉他们使用的.NET 2.0和.NET 3.5的一些功能。让我们一步一个脚印吧。

所以你给出一个ArrayList持以下资料:

{ "1:1", "0:0", "0:1", "2:1", "1:0", "2:0" } 

首先,什么是错误的使用正则表达式;也许是一个小小的表现处罚如果字符串真的如此简单,你可以用Split

string[] s = myArray[i].Split(new[] { ':' }); 
int val1 = int.Parse(s[0]); 
int val2 = int.Parse(s[1]); 

不过,既然你说你正在使用.NET 4,你真的不应该使用ArrayList在所有 - 注意,它需要你将你的值转换为适当的类型,例如string mystring = myArray[i] as string

有很多很棒的功能,你没有利用,如泛型(在.NET Framework 2.0以来)。让我们编写一个给定为ArrayList的函数,但返回排序后的通用List<string>(仅包含字符串的列表)。让我们一起来看看:

/// <summary> 
/// This method takes in an ArrayList of unsorted numbers in the format: a:b 
/// and returns a sorted List<string> with a descending, b ascending 
/// <summary> 
public List<string> SortMyValues(ArrayList unsorted) 
{ 
    // Declare an empty, generic List of type 'TwoNumbers' 
    List<MyTuple> values = new List<MyTuple>(); 
    foreach (object item in unsorted) 
    { 
     char[] splitChar = new char[] { ':' }; 
     string itemString = item as string; 
     string[] s = itemString.Split(splitChar); 
     values.Add(new MyTuple{ 
      FirstNumber = int.Parse(s[0]), 
      SecondNumber = int.Parse(s[1]) 
     }); 
    } 
    // Sort the values 
    values.Sort(); 
    // Return a list of strings, in the format given 
    List<string> sorted = new List<string>(); 
    foreach (MyTuple item in values) 
    { 
     sorted.Add(item.FirstNumber + ":" + item.SecondNumber); 
    } 
    return sorted; 
} 

public class MyTuple : IComparable { 
    public int FirstNumber { get; set; } 
    public int SecondNumber { get; set; } 

    public int CompareTo(object obj) 
    { 
     if (obj is MyTuple) 
     { 
      MyTuple other = (MyTuple)obj; 

      // First number descending 
      if (FirstNumber != other.FirstNumber) 
      return other.FirstNumber.CompareTo(FirstNumber); 
      // Second number ascending 
     return SecondNumber.CompareTo(other.SecondNumber); 
     } 
     throw new ArgumentException("object is not a MyTuple"); 
    } 
} 

现在,上面的代码工作,但真的长。请注意,您必须创建一个类来保存这两个值,使该类实现IComparable等等,非常讨厌!

.NET 3.5推出了一些伟大的功能,包括匿名类型LINQ。让我们更改我们的代码以使用这两个功能。

/// <summary> 
/// This method takes in an ArrayList of unsorted numbers in the format: a:b 
/// and returns a sorted List<string> with a descending, b ascending 
/// <summary> 
public List<string> SortMyValues(ArrayList unsorted) 
{ 
    // First, cast every single element of the given ArrayList to a string 
    // The Cast<T> method will do this, and return an enumerable collection 
    return unsorted.Cast<string>() 
     // Now, let's take this string data and create our objects that will hold two numbers 
     .Select(item => { 
      // This is the body of an anonymous method with one parameter, which I called 'item' 
      // This anonymous method will be executed for every element in the collection 
      string[] s = item.Split(new[] { ':' }); 
      // Here we create a new anonymous type holding our numbers 
      // No need to define a new dummy class! 
      return new { 
       FirstNumber = int.Parse(s[0]), 
       SecondNumber = int.Parse(s[1]) 
      }; 
     }) 
     // Now that we've got our objects, let's sort them 
     .OrderByDescending(x => x.FirstNumber) 
     .ThenBy(x => x.SecondNumber) 
     // Finally, now that we're sorted properly, let's format our string list output 
     .Select(x => x.FirstNumber + ":" + x.SecondNumber) 
     .ToList(); 
} 

我们的整个功能现在只有一行,大部分代码都是注释。我鼓励您了解并开始使用其中的一些功能;它会让你的代码更容易读写;-)

希望这有助于!

编辑:在resopnse到您的评论:

那么将会让他们按以下顺序:2:0 1:0 0:0 2:1 1:1 0:1

它看起来像你的第二个数字排序,上升,然后由第一个数字,下降。

只需更改上面的代码使用方法:

.OrderBy(x => x.SecondNumber) 
.ThenByDescending(x => x.FirstNumber) 
+0

明白了,谢谢! – 2011-04-03 18:05:01

+0

@casperOne - 我的错。我会纠正这个帖子;谢谢! – Pandincus 2011-04-07 12:36:07

2

这种感觉wird,但它的工作原理根据您的要求,也许,如果你分享更多的细节的我们可以帮助更精确的解决方案,有很多假设,现在试试这个:

var sortedStrings = new ArrayList(strings.ToArray() 
    .Select(s => new { parts = ((String)s).Split(':') }) 
    .OrderByDescending(p => p.parts[0]) 
    .ThenBy(p => p.parts[1]) 
    .Select(p => String.Concat(p.parts[0], ":", p.parts[1])).ToArray()); 
+0

+1工作正常:我会改变最后一行:.Select(p => string.Format(“{0}:{1}”,p.Parts [0],p.Parts [1]))。ToArray ();并且不需要强制转换为字符串(至少在VS 2010中) – Marcote 2011-04-03 03:09:41

4

虽然K Ivanovright idea,这里有一个版本,这也许是对眼睛更容易:

// Not sure what to call the "n:n" groupings. Assume 
// original is in an ArrayList named "pairs". 
IEnumerable<string> sortedPairs = 
    from pair in pairs.Cast<string>() 
    let parts = pair.Split(':') 
    let parsed = new { 
     Left = Int32.Parse(parts[0]), 
     Right = Int32.Parse(parts[1]), 
    } 
    orderby parsed.Left descending, parsed.Right 
    select pair; 

注意,对于解析像这样,正则表达式可能是有点矫枉过正(图案很简单,也很清楚) 。

此外,它假设您有双方的数字,根据您的示例。它也不会以任何方式改变字符串来返回结果。

+0

+1 - 这与我想出的非常接近。 @Mike:您可以对结果执行ToList()以获取List 。将ArrayList替换为其通用等价物(列表)。 – TrueWill 2011-04-03 03:20:43