C# - 对字符串的ArrayList进行排序

时间:2011-04-03 02:43:43

标签: c# sorting arraylist

我有一个ArrayList字符串,如下所示,我想输出一个以特定方式排序的新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

3 个答案:

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

请注意,对于这样的解析,正则表达式可能有点过分(模式非常简单,非常清晰)。

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

答案 1 :(得分:2)

这感觉很奇怪,但它的工作原理基于您的要求,也许如果您分享更多我们可以提供更多精确解决方案的细节,那么有许多假设,现在试试这个:

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());

答案 2 :(得分:1)

虽然我认为其他两个答案都是正确的,但我会假设你不熟悉他们使用的.NET 2.0和.NET 3.5的一些功能。让我们一步一步。

因此,您获得了ArrayList,其中包含以下数据:

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

首先,使用RegEx没有任何问题;也许是轻微的性能损失。如果字符串真的如此简单,您可以使用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

有很多很棒的功能,你没有利用它们,比如泛型(自2.0以来的.NET Framework)。让我们编写一个给定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();
}

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

希望这有帮助!

编辑:依旧评论:

  

按以下顺序排列它们需要什么:2:0 1:0 0:0 2:1 1:1 0:1

看起来你按第二个数字排序,升序,然后按第一个数字排序,降序。

只需更改上面的代码即可使用:

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