【问题标题】:which c# collection to use instead of List<KeyValuePair<string, double>>?使用哪个 c# 集合代替 List<KeyValuePair<string, double>>?
【发布时间】:2011-11-22 03:40:42
【问题描述】:

我要存储数据如

{
 {"apple",15   }
 {"pear",12.5  }
 {"", 10       }
 {"", 0.45     }
}

数据将绘制在条形图上(字符串为图例,双精度为值) 插入顺序很重要。 性能无所谓。 字符串可以重复或为空。(值也可以重复)

我需要获取最小值和最大值(如果可能的话很容易)来设置比例。

我用

List<KeyValuePair<string, double>> data = new List<KeyValuePair<string, double>>();
data.Add(new KeyValuePair<string,double>("",i));

相当无聊且难以阅读。 有更清洁的方法吗?

StringDoubleCollection data = new StringDoubleCollection();
data.add("apple",15);
data.add("",10);

double max = data.values.Max(); 
double min = data.values.Min();

如果不是如何轻松获得List&lt;KeyValuePair&lt;string, double&gt;&gt; 的最大值

NameValueCollection 看起来不错,但它是 &lt;string,string&gt; 我需要 &lt;string,double&gt;

【问题讨论】:

  • stackoverflow 通过不转义一些“> 和 NameValueCollection 的最大值,但它是一个 我需要一个
  • 为您修复了格式。
  • 你想要的基本上是一个允许重复键的字典。根据这个问题:stackoverflow.com/questions/146204/… 框架中没有任何东西支持它。您可能需要制作自己的 NameValueCollection 通用版本。
  • 感谢雷修复

标签: c# data-structures collections


【解决方案1】:

你可以像下面这样创建一个类:

class X
{
     public string Name { get; set; }
     public double Value { get; set; }

     // name is an optional parameter (this means it can be used only in C# 4)
     public X(double value, string name = "")
     {
         this.Name = name;
         this.Value = value;
     }

     // whatever
}

然后使用带有选择器的 LINQ 获取最大值和最小值:

var data = new List<X>();
data.Add(new X(35.0, "Apple"))
data.Add(new X(50.0));

double max = data.Max(a => a.Value);
double min = data.Min(a => a.Value);

编辑:如果上面的代码对您来说仍然无法阅读,请尝试使用运算符来改进它,以解决您只想获得该值的情况。

// Inside X class...
public static implicit operator X(double d)
{
    return new X(d);
}

// Somewhere else...
data.Add(50.0);

【讨论】:

  • 对不起,我在阅读时跳过了 duplicates 部分。还是编辑了:)
  • 最好只删除有关字典的部分,而不是让您的编辑解释它。封装类是一个有价值的建议,所以我投了赞成票。
【解决方案2】:

要确定您真正想要的数据结构,让我们看看您的使用模式。

  • 插入订单很重要。
  • 您不能通过密钥访问您的项目。
  • 你想要最小值和最大值。

堆提供最小值最大值,但不保留顺序。基于哈希的字典也不保留顺序。 List 实际上是您的数据结构的不错选择。它可用并提供出色的支持。

您可以通过为数据结构和条形数据定义类来美化您的代码。您可以向集合添加最小/最大功能。注意:我没有使用 Linq Min/Max 函数,因为它们返回最小值 value,而不是最小值 element

public class BarGraphData {
    public string Legend { get; set; }
    public double Value { get; set; }
}

public class BarGraphDataCollection : List<BarGraphData> {
    // add necessary constructors, if any

    public BarGraphData Min() {
        BarGraphData min = null;
        // finds the minmum item
        // prefers the item with the lowest index
        foreach (BarGraphData item in this) {
            if ( min == null )
                min = item;
            else if ( item.Value < min.Value )
                min = item;
        }
        if ( min == null )
            throw new InvalidOperationException("The list is empty.");
        return min;
    }

    public BarGraphData Max() {
        // similar implementation as Min
    }
}

【讨论】:

    【解决方案3】:

    你看过LookUp吗?

    唯一的问题是它是不可变的,所以你需要能够一次性创建你的集合。

    正如 Anthony Pegram 所说,创建一个有点痛苦。这取决于您的数据来自哪里。看看ToLookup 方法。

    【讨论】:

    • 这个问题是它不能直接实例化。你从别的东西开始,然后可以投射到这个。他首先需要一个中介结构。
    • 是的,这是真的。但根据他的数据来自哪里(没有提供信息),它仍然可能是可能的。无论如何都值得了解。
    【解决方案4】:

    如果为了可用性而这样做是值得的(即,您到处都在使用尴尬的 List&lt;KeyValuePair&lt;string, double&gt;&gt; 集合,那么实现 StringDoubleCollection 可能是值得的。用更友好的方式包装底层集合并不难您在示例中描述的语法。

    而且,正如其他 cmets / 答案所暗示的那样,该框架似乎没有提供更简单的解决方案来满足您的所有要求...

    至于“最大值”,我假设您的意思是具有最大值的键值对。可以这样检索:

    var max = list.Select(kvp => kvp.Value).Max();
    

    【讨论】:

      【解决方案5】:

      只需定义您自己的模型类来保存数据,而不是依赖于 KeyValuePair,一切都会变得更干净:

      using System;
      using System.Collections.Generic;
      
      public class Fruit
      {
          public string Name {get; set;}
          public double Price {get; set;}
      }
      
      public class Program
      {
          public static void Main()
          {
              List<Fruit> _myFruit = new List<Fruit>();
      
              _myFruit.Add(new Fruit{Name="apple", Price=15   });
              _myFruit.Add(new Fruit{Name="pear", Price=12.5  });
              _myFruit.Add(new Fruit{Name="",  Price=10       });
              _myFruit.Add(new Fruit{Name="",  Price=0.45     });
      
              // etc...
          }
      }
      

      【讨论】:

        【解决方案6】:

        如何实现 StringDoubleCollection 以按您的意愿工作......

        public class StringDoubleCollection
        {
            private List<KeyValuePair<string, double>> myValues;
            public List<double> values
            {
                get { return myValues.Select(keyValuePair => keyValuePair.Value).ToList(); }
            }
        
            public void add(string key, double value)
            {
                myValues.Add(new KeyValuePair<string,double>(key,value));
            }
        }
        

        【讨论】:

          【解决方案7】:

          你可以实现 Dictionary

             Dictionary<string, string> openWith = new Dictionary<string, string>();
          
          
             openWith.Add("txt", "notepad.exe");
             openWith.Add("bmp", "paint.exe");
             openWith.Add("dib", "paint.exe");
             openWith.Add("rtf", "wordpad.exe");
          

          https://docs.microsoft.com/pt-br/dotnet/api/system.collections.generic.dictionary-2?view=net-5.0

          【讨论】:

          • 在接受了不同的答案后,这个答案已经很晚了。它实际上也没有回答这个问题,因为原始问题询问了哪个集合用于字符串键和双精度值。你已经回答了字符串,字符串。请只回答增加了新价值的旧问题,在这种情况下,请确保您的答案解决了实际问题。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-11-22
          • 2019-09-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多