【问题标题】:How to sort a dictionary by key, if key is a list (in C#)?如果键是列表(在 C# 中),如何按键对字典进行排序?
【发布时间】:2017-02-09 16:51:49
【问题描述】:

我有一本字典(使用 C#):

Dictionary<List<string>, string> dictData = new Dictionary<List<string>, string>();

字典已经有值的地方(例如):

key: {"3", "1", "45"}, value: "test value 1"
key: {"1", "2", "45"}, value: "test value 2"
key: {"11", "1", "45"}, value: "test value 3"
key: {"1", "1", "45"}, value: "test value 4"

键是一个字符串列表,它总是至少有两个元素。我需要做的是按键对字典进行排序,或者更准确地说,按列表的第一个元素排序,并作为第二个标准按列表的第二个元素排序。字符串实际上是一个数字,所以它们应该按数字排序(“3”应该小于“11”)。所以对于上面的例子,我应该得到以下结果:

key: {"1", "1", "45"}, value: "test value 4"
key: {"1", "2", "45"}, value: "test value 2"
key: {"3", "1", "45"}, value: "test value 1"
key: {"11", "1", "45"}, value: "test value 3"

再次:如果键实际上是一个列表并且要由列表的第一个元素执行排序,然后由列表的第二个元素执行,我如何按键对字典进行排序?

【问题讨论】:

  • 我强烈建议不要使用 List 作为字典的键
  • 如果键是数字并且需要这样处理,为什么要使用字符串列表?
  • 除了不使用列表作为字典键之外:如果您真的需要,您可以使用带有自定义比较器的SortedDictionary

标签: c# linq list sorting dictionary


【解决方案1】:

如果您有两个 List&lt;int&gt; 包含:1、2、5 和 1、2、5,那么这两个列表不是同一个列表。它们是单独的列表实例,它们恰好包含相同顺序的相同值,因为列表(与其他集合类型一样,包括数组)是引用类型。您不能将它们用作唯一键,因为字典会将它们视为不同的键。

我建议创建一个包含您的三个值的struct,并将其用作键。原因是结构体是一个值类型,两个具有相同属性值的实例会被视为相等,这就是字典键所需要的。

struct Values
{
    public int First { get; set; }
    public int Second { get; set; }
    public int Third { get; set; }
}

那么你可以这样做:

var x = new Dictionary<Values, string>()
    {
        {new Values() {First = 1, Second = 1, Third = 45}, "test value 1"},
        {new Values() {First = 1, Second = 2, Third = 45}, "test value 2"},
        {new Values() {First = 11, Second = 1, Third = 45}, "test value 3"},
    };

var sorted = x.OrderBy(kvp => kvp.Key.First).Select(kvp => kvp.Value);

【讨论】:

    【解决方案2】:

    如果您确实需要将它作为您当前的设置,则可以使用(测试代码,需要对其进行调整)。它类似于原始答案,它只是完整列表(假设最多 3 个)。经过测试,似乎可以正常工作。如果它没有全部 3 个等,您需要添加逻辑。这只是让您开始的基本设置:

    private void DoIt()
        {
            Dictionary<List<string>, string> test = new Dictionary<List<string>, string>();
            List<string> workerList = new List<string>() { "3", "1", "45" };
            test.Add(workerList, "test value 1");
            workerList = new List<string>() { "1", "2", "45" };
            test.Add(workerList, "test value 2");
            workerList = new List<string>() { "11", "1", "45" };
            test.Add(workerList, "test value 3");
            workerList = new List<string>() { "1", "1", "45" };
            test.Add(workerList, "test value 4");
    
    
            foreach(KeyValuePair<List<string>,string> kvp in test.OrderBy(x => int.Parse(x.Key[0])).ThenBy(y => int.Parse(y.Key[1])).ThenBy(z => int.Parse(z.Key[2])))
            {
                Console.WriteLine("Key: " + kvp.Key[0].ToString() + "," + kvp.Key[1].ToString() + "," + kvp.Key[2].ToString() + " | " + "Value: " + kvp.Value.ToString());
            }
        }
    

    输出:

    Key: 1,1,45 | Value: test value 4
    Key: 1,2,45 | Value: test value 2
    Key: 3,1,45 | Value: test value 1
    Key: 11,1,45 | Value: test value 3
    

    【讨论】:

      【解决方案3】:

      要将列表用作字典的键,您可以执行以下操作

      public class DictionaryKeyList {
      
          public List<string> Lst { get; set; }
      
          public override bool Equals(Object otherObj){
              var otherList = otherObj as DictionaryKeyList;
      
              return !this.Lst.Zip(otherList, (a,b) => a == b).Any(x => !x);
          }
      

      然后使用字典作为类型

      Dictionary<DictionaryKeyList, string> dictData;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-02-11
        • 1970-01-01
        • 2012-02-18
        • 1970-01-01
        • 2019-02-08
        • 2019-12-30
        相关资源
        最近更新 更多