【问题标题】:Sorting a class string field property with numerical value [duplicate]用数值对类字符串字段属性进行排序[重复]
【发布时间】:2015-01-14 18:54:42
【问题描述】:

我有一个具有一个属性“名称”的类,其中包含 "1_[AnnualRevenue]","2_[ResellerType]","3_xxx".... 之类的名称

我的课是这样的

class xxx
{
 private string fileName;
 public string FileName
        {
            get { return fileName; }
            set { fileName = value; }
        }
}

我正在将值分配给类的对象。喜欢xxx.FileName="1_[AnnualRevenue]";

现在我有一个列表类。现在根据这个类属性对列表进行排序。

现在我想根据数字顺序对字段进行排序,我的意思是 1 前 2 秒等等。

然后将其写入文件流。

任何人都可以帮助我解决这个问题。 提前致谢。

【问题讨论】:

  • 您的意思是您有一个要按其名称属性排序的类列表?如果您展示了该类的代码示例以及您如何存储它的实例,将会很有帮助。
  • 请展示你的班级和价值观的例子
  • 您是在说文件名开头的“N_”数字吗?
  • dotnetperls.com/alphanumeric-sorting 这可以让你开始
  • 如果您正在考虑 _ 那么您没有进行数字排序,即字母数字排序,这会将 10_a 放在 2_a 之前

标签: c# asp.net sorting


【解决方案1】:

由于属性是String,但您想对其进行数字排序,可能最好的方法是在您的类上实现IComparable,然后将您的自定义排序代码放入CompareTo 方法中。那么就不用每次想要对列表进行排序时都编写更复杂的 Lambda 语句,只需调用列表上的Sort() 方法即可。

您还可以处理FileName 属性不包含下划线或为null 的情况,而不是在OrderBy 代码中出现异常(大多数其他答案都会发生这种情况)。

我还进行了一些其他更改 - 覆盖 ToString 方法,以便您可以轻松地将值显示到控制台窗口,并为 FileName 属性使用自动属性语法,以便我们可以删除支持字段:

class xxx : IComparable<xxx>
{
    public string FileName { get; set; }

    public int CompareTo(xxx other)
    {
        // Short circuit if any object is null, if the
        // Filenames equal each other, or they're empty
        if (other == null) return 1;
        if (FileName == null) return (other.FileName == null) ? 0 : -1;
        if (other.FileName == null) return 1;
        if (FileName.Equals(other.FileName)) return 0;
        if (string.IsNullOrWhiteSpace(FileName)) 
            return (string.IsNullOrWhiteSpace(other.FileName)) ? 0 : -1; 
        if (string.IsNullOrWhiteSpace(other.FileName)) return 1;

        // Next, try to get the numeric portion of the string to compare
        int thisIndex;
        int otherIndex;

        var thisSuccess = int.TryParse(FileName.Split('_')[0], out thisIndex);
        var otherSuccess = int.TryParse(other.FileName.Split('_')[0], out otherIndex);

        // If we couldn't get the numeric portion of the string, use int.MaxValue
        if (!thisSuccess)
        {
            // If neither has a numeric portion, just use default string comparison
            if (!otherSuccess) return FileName.CompareTo(other.FileName);
            thisIndex = int.MaxValue;
        }
        if (!otherSuccess) otherIndex = int.MaxValue;

        // Return the comparison of the numeric portion of the two filenames
        return thisIndex.CompareTo(otherIndex);
    }

    public override string ToString()
    {
        return FileName;
    }
}

现在,您只需拨打名单上的Sort

List<xxx> list = new List<xxx>
{
    new xxx {FileName = "13_a"},
    new xxx {FileName = "8_a"},
    new xxx {FileName = null},
    new xxx {FileName = "1_a"},
    new xxx {FileName = "zinvalid"},
    new xxx {FileName = "2_a"},
    new xxx {FileName = ""},
    new xxx {FileName = "invalid"}
};

list.Sort();

Console.WriteLine(string.Join("\n", list));

// Output (note the first two are the empty string and the null value):
// 
// 
// 1_a
// 2_a
// 8_a
// 13_a
// invalid
// zinvalid

【讨论】:

  • 顺便说一句,不知道你是如何想出文件名的,但如果你在代码中的某个地方添加数字,给你的班级一个@可能会更容易987654333@ 属性并在 FileName 之外进行设置。如果你这样做了,那么你可以这样做:list.OrderBy(i =&gt; i.Rank),你不必创建自定义的 CompareTo 方法。
【解决方案2】:

您可以使用 LINQ 为您完成这项工作

List<xxx> orderedList = unOrderedList.OrderBy(o => Convert.ToInt32(o.FileName.Split('_').First())).ToList();

代表 cmets 编辑了答案 - 指出我们确实需要转换为整数才能正确排序。

【讨论】:

  • 10_a、20_a放在哪里,解决方法同上
  • 虽然我需要尝试,但这听起来不错,纯数字排序
【解决方案3】:

您可以按照以下方式对列表进行排序:

List<xxx> list = new List<xxx> 
{ 
    new xxx { FileName = "3_a" }, 
    new xxx { FileName = "1_a" }, 
    new xxx { FileName = "2_a" }, 
    new xxx { FileName = "8_a" } 
};
var sorted = list.OrderBy(it => Convert.ToInt32(it.FileName.Split('_')[0]));//using System.Linq;

您可以将列表写入磁盘文件,如下所示:

using (TextWriter tw = new StreamWriter("C:\\FileNames.txt"))
            {
                foreach (var item in sorted)
                {
                    tw.WriteLine(item.FileName.ToString());
                }
            }

【讨论】:

  • 10_a、20_a 会放在哪里
  • 不错!可能不需要在 FileName 上调用.ToString()...:p
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-06
  • 2021-06-27
相关资源
最近更新 更多