繁体   English   中英

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

[英]C# - Sorting an ArrayList of strings

我有一个看起来像下面的字符串的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

尽管K Ivanov正确的想法 ,但以下版本可能更容易出现:

// 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;

请注意,对于此类解析,正则表达式可能会有点过大(模式非常简单且非常清晰)。

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

这种感觉很奇怪,但是它可以根据您的要求工作,也许,如果您分享更多的细节,我们可以为您提供更精确的解决方案,那么有很多假设,现在尝试一下:

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

虽然我认为其他两个答案都是正确的,但我将假设您不熟悉它们使用的.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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM