如何对列表<string> / 字符串版本号数组进行排序?

Posted

技术标签:

【中文标题】如何对列表<string> / 字符串版本号数组进行排序?【英文标题】:How to sort a list<string> / array of string version number? 【发布时间】:2016-10-01 12:57:21 【问题描述】:

我有一个版本字符串列表(见图),我想按降序对它们进行排序。

我见过一些使用 Version 类来比较它们的解决方案,但我想不出任何解决方案可以像这样对整个列表进行排序。实现这一目标的最简单的方法是什么?

【问题讨论】:

List&lt;Version&gt; 是最简单的。包含数字的字符串不会对列表数字进行排序。或者,查找/使用自然排序 旁注:请不要在您的帖子中添加“谢谢”和“搜索了很多”文本。为了展示研究成果,请提供您尝试过的方法的链接,并简要说明为什么它没有解决您的问题。 【参考方案1】:

这个简单的实现有什么问题?

using System;
using System.Collections.Generic;

namespace ConsoleApplication1

    class Program
    
        static void Main(string[] args)
        
            var ver = new List<Version>();

            ver.Add(new Version("3.5"));
            ver.Add(new Version("3.15"));
            ver.Add(new Version("3.10"));
            ver.Add(new Version("3.1"));

            ver.Sort();
            ver.Reverse();
        
    

【讨论】:

没想到。当我阅读 Version 类时,我认为我只需要在 2 个对象之间进行比较【参考方案2】:

你可以使用 IComparable

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2

    class Program
    
        static void Main(string[] args)
        
              List<string> data = new List<string>
                "3.5.0.1", "3.4.1.9", "3.4.1.56", "3.4.1.55", "3.4.1.46",
                "3.4.1.45", "3.4.1.44", "3.4.1.30", "3.4.1.3", "3.4.1.22",
                "3.4.1.2", "3.4.1.11", "3.4.1.0", "3.4.0.7", "3.4.0.3",
                "3.4.0.1", "3.3.0.8", "3.3.0.4", "3.3.0.0", "3.2.0.9",
                "3.2.0.6", "3.2.0.3", "3.2.0.27", "3.2.0.20", "3.2.0.15",
                "3.2.0.1", "3.2.0.0", "3.1.0.7", "3.1.0.15", "3.1.0.14"
              ;
              List<SortPara> sortPara = data.Select(x => new SortPara(x)).ToList();
              data = sortPara.OrderBy(x => x).Select(x => x.strNumbers).ToList();
              data = sortPara.OrderByDescending(x => x).Select(x => x.strNumbers).ToList();
        

    
    public class SortPara : IComparable<SortPara>
    
        public List<int> numbers  get; set; 
        public string strNumbers  get; set; 
        public SortPara(string strNumbers)
        
            this.strNumbers = strNumbers;
            numbers = strNumbers.Split(new char[]  '.' ).Select(x => int.Parse(x)).ToList();

        
        public int CompareTo(SortPara other)
        
            int shortest = this.numbers.Count < other.numbers.Count ? this.numbers.Count : other.numbers.Count;
            int results = 0;
            for (int i = 0; i < shortest; i++)
            
                if (this.numbers[i] != other.numbers[i])
                
                    results = this.numbers[i].CompareTo(other.numbers[i]);
                    break;
                
            
            return results;
        
    

【讨论】:

我认为这样的事情太过分了 只因为有版本方法。这是如何使用 CompareTo() 方法创建自定义 IComparable 方法的一个很好的示例。 @JackLe 这实际上是一个矫枉过正的唯一原因是这些方法已经存在于最新的 C# 库中,但是您可能会发现此代码 sn-p 非常有用,因为您需要将 object x 与 @ 进行比较987654323@ 必须实现一个自定义的IComparable 接口。【参考方案3】:

您应该使用IComparable 作为 jdweng,只需稍作编辑即可比较“2.1.0.4”和“2.1”等版本:

public int CompareTo(SortPara other)
    
        int shortest = this.numbers.Count < other.numbers.Count ? this.numbers.Count : other.numbers.Count;
        int results = 0;
        for (int i = 0; i < shortest; i++)
        
            if (this.numbers[i] != other.numbers[i])
            
                results = this.numbers[i].CompareTo(other.numbers[i]);
                break;
            
        
        if (results != 0)
            return results;
        if (this.numbers.Count > other.numbers.Count)
            return 1;
        else if (this.numbers.Count < other.numbers.Count)
            return -1;
        else
            return 0;
    

【讨论】:

您可以通过返回两个计数来省略最后的所有 if-else:return this.numbers.Count - other.numbers.Count;。如果在 for 循环中返回,则可以删除变量 results 和 break。计算最短使用 Math.Min(this.numbers.Count, other.numbers.Count);【参考方案4】:

这是对语义版本控制 (https://semver.org) 进行排序的解决方案。 Nuget.Core 提供了一个 SemanticVersion 类,其运行方式与 .net 中的标准 Version 类非常相似。它会将您的字符串解析为 IComparable 和 IEquatable 对象,以便您可以比较多个版本或在集合中对它们进行排序等。

Nuget.Core:https://www.nuget.org/packages/nuget.core/(你可以通过 nuget 拉取这个库)

https://github.com/NuGet/NuGet2/blob/2.13/src/Core/SemanticVersion.cs

var rawVersions = new [] "v1.4.0", "v1.4.0-patch10", "v1.4.0-patch2";
var versions = rawVersions.Select(v => new SemanticVersion(v));
var sorted = versions.ToList().Sort();

【讨论】:

以上是关于如何对列表<string> / 字符串版本号数组进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用另一个列表中的项目顺序对字符串列表进行排序?

如何根据特定索引范围对 ArrayList<String> 进行排序

如何在 Dart 中对字符串列表进行排序?

如何使用许多字符串值初始化字符串列表 (List<string>)

如何将 HashMap<String, ArrayList<String>> 存储在列表中?

如何在颤动中将 List<String> 转换为 String [重复]