【问题标题】:C# - Sorting an ArrayList of stringsC# - 对字符串的 ArrayList 进行排序
【发布时间】:2011-07-28 11:41:21
【问题描述】:

我有一个如下所示的字符串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

【问题讨论】:

  • @Mike - 是否可以将信息存储为对象而不是字符串?即它们需要是字符串,还是仅在输出时才需要?
  • @Pandincus:我想再次将它们作为排序字符串输出。但如果这样更容易,我想那就没问题了。
  • @Mike - 另外,您使用的是什么版本的 .NET Framework?
  • .NET 框架版本 4
  • 请停止使用 ArrayList 列表。从 .net 2 开始,您可以使用强类型通用列表:List<string>

标签: c# sorting arraylist


【解决方案1】:

虽然K Ivanov 有right 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 - 这与我想出的非常接近。 @Mike:您可以对结果执行 ToList() 以获取 List。将 ArrayList 替换为其通用等效项 (List)。
【解决方案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());

【讨论】:

  • +1 工作正常:我将更改最后一行: .Select(p => string.Format("{0}:{1}", p.Parts[0], p.Parts [1])).ToArray();并且不需要强制转换为字符串(至少在 VS 2010 中)
【解决方案3】:

虽然我认为其他两个答案都是正确的,但我假设您不熟悉他们使用的 .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&lt;string&gt;(一个只包含字符串的列表)。让我们看看:

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

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

希望这有帮助!

编辑:回应您的评论:

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

您似乎是按第二个数字升序排序,然后按第一个数字降序排序。

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

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

【讨论】:

    猜你喜欢
    • 2014-12-07
    • 1970-01-01
    • 2012-12-24
    • 2011-11-26
    • 2017-06-07
    • 1970-01-01
    • 2012-02-24
    • 2017-02-23
    • 1970-01-01
    相关资源
    最近更新 更多