c#NameValueCollection不同的值

时间:2016-03-29 06:05:59

标签: c# distinct namevaluecollection

C#代码如下:

NameValueCollection nvc = new NameValueCollection();
nvc.Add("color", "red");
nvc.Add("size", "s");
nvc.Add("color", "red");
nvc.Add("size", "m");
nvc.Add("color", "red");
nvc.Add("size", "l");

//blue
nvc.Add("color", "blue");
nvc.Add("size", "m");
nvc.Add("color", "blue");
nvc.Add("size", "l");
//green
nvc.Add("color", "green");
nvc.Add("size", "s");
nvc.Add("color", "green");
nvc.Add("size", "m");
nvc.Add("color", "green");
nvc.Add("size", "l");

实际结果:

color:red,red,red,blue,blue,green,green,green 
size:s,m,l,m,l,s,m,l 

希望结果:

color:red,blue,green     
size:s,m,l 

3 个答案:

答案 0 :(得分:2)

有些想法:

  1. NameValueCollection允许重复值。使用Dictionary<string, string>
  2. NameValueCollection是较旧的对象,仅强类型为string, stringDictionary更灵活,因为您可以指定类型参数。
  3. 使用Dictionary时请注意,如果您尝试两次添加相同的密钥,则会出现错误。这可以通过稍微更改语法来解决。而不是Add(),只需使用索引器:

    var myDict = new Dictionary<string, string>();
    myDict["color"] = "blue";
    myDict["color"] = "blue"; // no harm doing this twice
    
  4. 根据我的经验,在整个地方使用字符串是一种让bug陷入其中的方法,并且很容易出错(嗯,我想知道我怎么知道这个?)。拼错一些东西太容易了,或者为一种颜色指定尺寸,反之亦然。

    您是否有理由在代码中强力键入概念?

    public abstract class ProductAttribute { }
    
    public sealed class Color : ProductAttribute {
        private Color(string value) { Value = value; }
        public Value { get; }
    
        public static readonly Blue = new Color("blue");
        public static readonly Green = new Color("green");
    
        private static readonly IReadOnlyDictionary<string, Color> _colorDict = 
           new ReadOnlyDictionary<string, Color>(
              new List<Color> {
                 Blue, Green
              }.ToDictionary(color => color.Value, color => color)
           );
    
        public static Color GetColor(string value) {
           Color color;
           _colorDict.TryGetValue(value, out color);
           return color;
        }
    }
    

    然后为尺寸做类似的事情。这只是一个想法,也许不是很灵活(您必须更改代码以添加新值),但它应该向您展示可能的内容。

    但看看你现在能做什么:

    var attrs = new HashSet<ProductAttribute>;
    attrs.Add(Color.Blue);
    attrs.Add(Color.Green);
    attrs.Add(Color.Blue); // no problem
    attrs.Add(Color.GetColor("blue")); // no problem
    attrs.Add(Size.Small);
    attrs.Add(Size.Medium);
    attrs.Add(Size.Medium); // no problem
    

    使用ProductAttribute类的一种方法是这样的:

    foreach (ProductAttribute attr in attrs) {
       Color color = attr as Color;
       if (color != null) {
          // work with color
       }
    }
    

    或者,您可以创建ProductAttributeType枚举,将其作为参数添加到ProductAttribute构造函数中,并将其公开在ProductAttribute类的只读抽象属性中。然后,所有子类都以它们的类型传递,例如,您可以轻松获取仅执行attr.ProductAttributeType == ProductAttributeType.Color的类型。

答案 1 :(得分:0)

我不确定您的用例,NameValueCollection允许重复更好地使用Dictionary来处理此类情况。

你仍然可以在NameValueCollection上做同样的事情来获得你想要的结果。

var results = nvc.AllKeys
    .GroupBy(g=>g)
    .Select(s=> 
            new 
            {
                key = s.Key,  
                values = nvc.GetValues(s.Key).Distinct() 
            }); 


foreach(var result in results)
{
    Console.WriteLine("{0}- {1}", result.key, string.Join(",", result.values) ;
}

工作Example

答案 2 :(得分:0)

老问题,但是我需要类似的东西(在VB.Net中但很容易在C#中应用);我正在使用该集合来编译单词/单词组和值之间的引用,而忽略大小写。字典解决方案会覆盖值,仅保留最后一个值,并且与列表绑定的字典变得比我不愿花力气的维护工作更多。为了确切地得到要问的内容,我首先使用以下语法添加了一种对我有用的方法:

If Not nvc.AllKeys.Contains(name) OrElse Not nvc.GetValues(name).Contains(value) Then nvc.Add(name, value)

大量重复调用相同的键和值将不会非常有效,但这可能是我能找到的最简单的方法。这最终变得多余,并且以我的代码名称(有时甚至是值)被临时构建。为了尽可能减少代码/变量并提高效率(仍然使用这种效率低下的方法),我首先考虑构建一个 Sub,但创建了以下代码:

Private Class NoDupValueNameValueCollection
    Inherits Collections.Specialized.NameValueCollection
    Public Overrides Sub Add(name As String, value As String)
        If Not MyBase.AllKeys.Contains(name) OrElse Not MyBase.GetValues(name).Contains(value) Then MyBase.Add(name, value)
    End Sub
End Class

或C#

    private class NoDupValueNameValueCollection : System.Collections.Specialized.NameValueCollection {
        public override void Add(string name, string value) {
            if (!(base.AllKeys.Contains(name)) || !(base.GetValues(name).Contains(value))) base.Add(name, value);
        }
    }

现在可以代替nvc并完全使用它,并且可以防止重复值。实际上,这正是所要问的:一个NameValueCollection,可以防止添加重复的值

相关问题