简体   繁体   English

C#NameValueCollection不同的值

[英]c# NameValueCollection distinct values

C# code as below: 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");

actual result: 实际结果:

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

hope result: 希望结果:

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

Some thoughts for you: 对您的一些想法:

  1. NameValueCollection allows duplicate values. NameValueCollection允许重复的值。 Use a Dictionary<string, string> . 使用Dictionary<string, string>
  2. NameValueCollection is an older object that is strongly typed to string, string only. NameValueCollection是一个较旧的对象,强烈将其键入string, stringstring, string Dictionary is more flexible, because you can specify the type parameters. Dictionary更加灵活,因为您可以指定类型参数。
  3. When using Dictionary note that you will get errors if you try to add the same key twice. 使用Dictionary请注意,如果尝试两次添加相同的密钥,则会出错。 This can be remedied by changing your syntax slightly. 可以通过稍微更改语法来解决。 Instead of Add() , just use the indexer: 代替Add() ,只需使用索引器即可:

     var myDict = new Dictionary<string, string>(); myDict["color"] = "blue"; myDict["color"] = "blue"; // no harm doing this twice 

In my experience, using strings all over the place is a way to let bugs creep in, and makes it easy to make mistakes (hmmm, wonder how I know this?). 以我的经验,到处使用字符串是一种使错误蔓延的方式,并且易于出错(嗯,想知道我怎么知道吗?)。 It's too easy to misspell something, or assign a size to a color or vice versa. 拼写错误或为颜色分配大小是很容易的,反之亦然。

Is there a reason you can't strongly type the concepts in your code? 您有理由不能在代码中强烈键入概念吗?

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;
    }
}

Then do something similar for sizes. 然后对尺寸进行类似的处理。 This is just one idea, perhaps not very flexible (you have to change the code to add new values), but it should show you what's possible. 这只是一个想法,也许不是很灵活(您必须更改代码以添加新的值),但是它应该向您显示可能的方法。

But look what you can do now: 但是看看您现在可以做什么:

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

One way to work with the ProductAttribute classes is like so: 使用ProductAttribute类的一种方法如下:

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

Alternately, you can create a ProductAttributeType enum, add it as a parameter in the ProductAttribute constructor and expose it in a read-only abstract property in the ProductAttribute class. 或者,您可以创建一个ProductAttributeType枚举,将其添加为ProductAttribute构造函数中的参数,并在ProductAttribute类的只读抽象属性中公开它。 Then all your subclasses pass in what type they are, and you can easily get the type of something just doing attr.ProductAttributeType == ProductAttributeType.Color for example. 然后,所有子类都传递它们的类型,例如,您可以轻松地进行attr.ProductAttributeType == ProductAttributeType.Color来获取某种类型的东西。

I'm not sure on your use case, NameValueCollection allows duplicates better to use Dictionary for such cases. 我不确定您的用例, NameValueCollection允许重复项更好地用于此类情况的Dictionary

Still you could do something like this on NameValueCollection to get the results you want. 仍然可以在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) ;
}

Working Example 工作Example

Old question but I needed something similar(in VB.Net but easily applicable in C#); 老问题,但我需要类似的东西(在VB.Net中,但很容易在C#中应用); am using the collection to compile references between words/word groups and values while ignoring case. 我正在使用该集合来编译单词/单词组和值之间的引用,而忽略大小写。 The dictionary solutions overwrite values, maintaining only the last value and a dictionary tied to a list becomes more plumbing maintenance than I like to bother with. 字典解决方案会覆盖值,仅保留最后一个值,并且与列表绑定的字典变得比我不愿花力气的维护工作更多。 To get exactly what is being asked, in a way that worked for me I first used the following syntax to add: 为了确切地得到要问的内容,我首先使用以下语法添加了一种对我有用的方法:

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

Large numbers of repeated calls to the same keys and values wont be very efficient but this is probably the simplest way I could find. 大量重复调用相同的键和值将不会非常有效,但这可能是我能找到的最简单的方法。 This ended up being redundant and in my code name(and sometimes even value)was being built ad-hoc; 这最终变得多余,并且以我的代码名称(有时甚至是值)被临时构建。 in order to reduce code/variables and increase efficiency as much as I could(still using this somewhat inefficient method), I first considered building an <Extension()> Sub but instead created this: 为了尽可能减少代码/变量并提高效率(仍然使用这种效率低下的方法),我首先考虑构建<Extension()> 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

or C# 或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);
        }
    }

It can now be used in place of and exactly as nvc and will prevent duplicate values. 现在可以代替nvc使用它,并且可以防止重复值。 In fact it is exactly what is being asked: a NameValueCollection that prevents the addition of duplicate values 实际上,这正是所要问的:一个NameValueCollection,它防止添加重复值

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM