1

我想使用索引对字符串进行排序,但它在第 10 个索引之后不起作用,在使用 Sort() 方法后在列表中的第一个索引之后添加了第 10 个/以后的索引。

我试过下面的代码,但它不起作用。

List<string> stringList = new List<string>();

foreach (ManagementObject disk in objectSearcher.Get() )
{
    stringList.Add(string.Format("{0, -15} {1,-35} {2, -20}",
                                disk.GetPropertyValue("Index"),
                                disk.GetPropertyValue("Model"),
                                diskSize));
}
stringList.Sort();

在上述场景中,代码对于 0-9 索引工作正常,但对于后面的索引,这不能按预期工作。

4

4 回答 4

8

将您的对象放入类结构中并尽可能长时间地使用该强类型:

public class DiskInfo
{
    private int index = 0;
    private string model = String.Empty;
    private unsigned long size = 0;

    public int getIndex() { return index; }
    public string getModel() { return model; }
    public unsigned long getSize() { return size; }

    public DiskInfo(int index, string model, unsigned long size)
    {
        this.index = index;
        this.model = model;
        this.size = size;
    }

    public string ToString()
    {
        return string.Format("{0, -15} {1,-35} {2, -20}", index, model, size);
    }
}
// ...
List<DiskInfo> lst = new List<DiskInfo>();
foreach (ManagementObject disk in objectSearcher.Get() )
{
    lst.Add(new DiskInfo(
        disk.GetPropertyValue("Index"),
        disk.GetPropertyValue("Model"),
        diskSize
    ));
}

根据需要调整类型。
然后你可以使用简单的 linq 进行排序。

lst = lst.OrderBy(x => x.getIndex());

最重要的是,您可以获得 IDE 支持和编译器错误,而不是试图弄清楚为什么在处理字符串时会出现格式异常等。如果您的输入数据不是正确的数据类型,那么就在那里进行转换。
例如,索引作为字符串传递:

string strIdx = "15";
lst.Add(new DiskInfo(int.Parse(strIdx)), ...)
于 2019-06-17T11:56:37.627 回答
1

它在第 10 个索引之后不起作用。

那是因为 List().Sort 调用了字符串的比较函数。在字符串比较中“0”小于“1”,“1”小于“11”,“12”小于“2”等。所以它是10点后不工作。

您可以定义一个示例比较函数,如下所示:

 public static int Compare(string a, string b)
        {
            return int.Parse(a.Substring(0, 15)).CompareTo(int.Parse(b.Substring(0, 15)));
        }

然后在 sort 方法中调用它:

stringList.Sort(Compare);

前提是您的格式满足其前 15 个字符可以转换为整数。

于 2019-06-17T12:05:23.057 回答
0

您似乎故意将您的数字左对齐索引,这意味着从 1 到 12 的升序字符串排序序列将是1, 11, 12, 2, 3, 4, ...

由于您在创建字符串期间拥有索引值,因此再次从字符串中解析出数字以对其进行排序是很浪费的。最好将索引和字符串分别保留在合适的数据结构中,按索引排序,然后只投影出字符串。

更新了 OP 的新问题

IComparable每次您需要按其属性之一对相关数据的可枚举进行排序时,创建自定义 POCO 类(有或没有实现)似乎都是多余的。

相反,您可以轻松构建包含可排序整数和连接字符串的可排序匿名类、结构或元组,然后排序,然后仅投影字符串。无论哪种方式,OP 的GetPropertyValue方法似乎都返回(反映)弱类型,例如objector string- 接受的答案不会编译,因为它需要将索引转换为int.

这是值元组解决方案:

var tuples = new List<(int index, string str)>();

foreach (ManagementObject disk in objectSearcher.Get() )
{
    var indexValue = int.Parse(disk.GetPropertyValue("Index"));
    tuples.Add((indexValue, string.Format("{0, -15} {1,-35} {2, -20}",
                                indexValue,
                                disk.GetPropertyValue("Model"),
                                diskSize)));
}

// Sort by index, and project out the assembled string.
var myList = tuples
          .OrderBy(t => t.index)
          .Select(t => t.str)
          .ToList();

原始答案,OP有一个简单的循环

我在下面所做的是保留原始字符串的 Value 元组,以及前 15 位的解析整数值。

请注意,如果字符串的前 15 个字符中有非数字字符,这将中断。

// Test Data
var strings = Enumerable.Range(0, 12)
  .Select(i => (string.Format("{0, -15} {1,-35} {2, -20}", i, "Model", "35GB")));

// Project out a tuple of (index, string)    
var indexedTuples = strings.Select(s => (idx: int.Parse(s.Substring(0, 15)), str: s));
var sorted = indexedTuples.OrderBy(t => t.idx)
                          .Select(t => t.str);
于 2019-06-17T11:44:49.943 回答
0

您可能正在寻找在 Windows 资源管理器中看到的“逻辑排序顺序”。下面我使用该 API 将默认字符串比较器替换为比较器:StrCmpLogicalW

class Program
{
    public sealed class NaturalStringComparer : IComparer<string>
    {
        [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
        public static extern int StrCmpLogicalW(string psz1, string psz2);

        public int Compare(string a, string b) => StrCmpLogicalW(a, b);
    }

    static void Main()
    {
        var stringList = new List<string>();

        var index = 0;
        while (index < 12)
        {
            stringList.Add($"{index,-15} {"Model",-35} {"35GB",-20}");
            index++;
        }

        stringList.Sort(new NaturalStringComparer());

        foreach (var s in stringList)
        {
            Console.WriteLine(s);
        }
    }
}
于 2019-06-17T11:59:57.557 回答