You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让C# SortedList的嵌套字符串按键实现数值排序?

Great observation on how SortedList handles different key types! The issue you're facing with semicolon-separated string keys (like "0;0", "0;10") is that the default string comparer uses lexicographical order, which doesn't align with numerical sorting for your composite keys. Let's break down how to fix this, leveraging the work you've already done with your Plates class.

Core Idea

We need to compare these string keys by first splitting them into integer arrays, then comparing the arrays numerically (element by element). Since you already have a Comparer<int[]> implementation in your Plates class, we can reuse that logic to build a custom string key comparer for SortedList.


Step 1: Ensure Your int[] Comparer is Fully Implemented

First, make sure your Plates class's Compare method correctly handles numerical sorting of integer arrays. Here's a robust example if you haven't finalized it:

public class Plates : Comparer<int[]>, IEnumerable<KeyValuePair<string, Plate>>
{
    // Implement the integer array comparison logic
    public override int Compare(int[] x, int[] y)
    {
        if (x == null && y == null) return 0;
        if (x == null) return -1;
        if (y == null) return 1;

        // Compare elements one by one until a difference is found
        int minLength = Math.Min(x.Length, y.Length);
        for (int i = 0; i < minLength; i++)
        {
            int elementComparison = x[i].CompareTo(y[i]);
            if (elementComparison != 0)
                return elementComparison;
        }

        // If all compared elements are equal, shorter array comes first
        return x.Length.CompareTo(y.Length);
    }

    // Rest of your Plates class implementation (IEnumerable, etc.) goes here
}

Step 2: Build a Custom String Key Comparer

Create an IComparer<string> that converts your semicolon-separated keys to int[] and uses your existing array comparer to determine order:

public class SemicolonKeyComparer : IComparer<string>
{
    private readonly Comparer<int[]> _arrayComparer;

    // Use your Plates class's array comparison logic
    public SemicolonKeyComparer(Plates platesComparer)
    {
        _arrayComparer = platesComparer ?? new Plates();
    }

    public int Compare(string x, string y)
    {
        if (string.IsNullOrEmpty(x) && string.IsNullOrEmpty(y)) return 0;
        if (string.IsNullOrEmpty(x)) return -1;
        if (string.IsNullOrEmpty(y)) return 1;

        // Split strings into integer arrays
        int[] xArray = x.Split(';').Select(int.Parse).ToArray();
        int[] yArray = y.Split(';').Select(int.Parse).ToArray();

        // Reuse the array comparison logic from Plates
        return _arrayComparer.Compare(xArray, yArray);
    }
}

Step 3: Integrate the Comparer with Your SortedList

Update your Plates class to use this custom comparer when initializing its internal SortedList (assuming you're using a SortedList as the backing store):

public class Plates : Comparer<int[]>, IEnumerable<KeyValuePair<string, Plate>>
{
    private readonly SortedList<string, Plate> _internalSortedList;

    public Plates()
    {
        // Initialize the SortedList with our custom key comparer
        _internalSortedList = new SortedList<string, Plate>(new SemicolonKeyComparer(this));
    }

    // Add method to insert new plates
    public void Add(string key, Plate plate)
    {
        _internalSortedList.Add(key, plate);
    }

    // Implement IEnumerable to expose sorted key-value pairs
    public IEnumerator<KeyValuePair<string, Plate>> GetEnumerator()
    {
        return _internalSortedList.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    // Your existing Compare method from Step 1 goes here
}

Testing the Solution

When you use the Plates class now, your keys will sort numerically instead of lexicographically:

var plates = new Plates();
plates.Add("0;10", new Plate());
plates.Add("0;2", new Plate());
plates.Add("1;0", new Plate());

// Iterating over plates will return keys in this order: "0;2", "0;10", "1;0"

Notes

  • Add error handling if your keys might contain non-numeric values (e.g., wrap int.Parse in a try-catch block or use int.TryParse).
  • This approach works for any number of semicolon-separated segments (e.g., "1;2;3" will sort correctly against "1;2;10").

内容的提问来源于stack exchange,提问作者PetrasVestartasEPFL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 06:42:50