I have a list of dictionary:
List<Dictionary<string, string>> items = new List<Dictionary<string, string>>();
foreach (var group in groupedItems)
{
foreach (var item in group)
{
Dictionary<string, string> newItem = new Dictionary<string, string>();
newItem.Add("name", item.Name);
newItem.Add("value", item.Value);
}
}
items.Add(newItem);
Basically when I loop through the grouped items, I create a Dictionary where the key is the item.Name and value is item.Value. In a grouped case, this will result in duplicate dictionaries to the list.
How can I avoid adding duplicate Dictionary to this List?
I have a foreach loop and I want to add some items once.
First thing that comes to mind would be to create your own class which extends Dictionary<string, string> and implement your own version of GetHashCode() and Equals:
public class MyDictionary : Dictionary<string, string>
{
public override int GetHashCode()
{
...
}
public override bool Equals(object source)
{
...
}
}
Within the Equals you implement your equality mechanism, and in GetHashCode you implement a mechanism which yields the same numeric value for two dictionaries which are the same, according to your equality criteria.
Then, instead of a List<Dictionary<string, string>>, you use a HashSet<MyDictionary>. Since sets do not allow duplicates, you should end up with a collection of unique dictionary collections.
I solved this in this way:
I created a new dictionary:
Dictionary<string, string> control = new Dictionary<string, string>();
And then I just do like this:
Dictionary<string, string> newItem = new Dictionary<string, string>();
newItem.Add("name", item.Name);
newItem.Add("value", item.Value);
if (!control.ContainsKey(item.Name))
{
control.Add(item.Name);
items.Add(newItem);
}
You can implement your own EqualityComparer to determine if two dictionaries are equal:
class EqualityComparer<Dictionary<string, string>> : IEqualityComparer<Dictionary<string, string>>
{
public bool Equals(Dictionary<string, string> x, Dictionary<string, string> y)
{
// your code here
}
public int GetHashCode(Dictionary<string, string> obj)
{
// your code here
}
}
Now you may use this comparer within a check for existance of a new item:
foreach (var g in groupedItems)
{
Dictionary<string, string> newItem = new Dictionary<string, string>();
foreach(var item in g)
{
newItem.Add("name", item.Name);
newItem.Add("value", item.Value);
}
if (!items.Contains(newItem, new EqualityComparer()) items.Add(newItem);
}
Thus there is no need to create a new implementation of Dictionary.
Related
I want to group by my list of dictionaries dynamically just like:
public static List<Dictionary<string, ClassName>> GroupBy(this List<Dictionary<string, ClassName>> list)
{
return list.AsQueryable().GroupBy(i => new { Key1 = i["Key01"].ClassProperty, Key2 = i["Key02"].AnotherClassProperty });
}
but I need to set keys name and numbers dynamically.
I had an idea to create dynamic-typed variable using ExpandoObject like that:
public static List<Dictionary<string, ClassName>> GroupBy(this List<Dictionary<string, ClassName>> list, IEnumerable<string> fieldnames)
{
return list.AsQueryable().GroupBy(i => GetKeys(fieldnames, dict) });
dynamic GetKeys(IEnumerable<string> fieldnames, Dictionary<string, ClassName> dict)
{
IDictionary<string, object> sampleObject = new ExpandoObject();
foreach (var fieldname in fieldnames)
{
sampleObject.Add($"Key{sampleObject.Count}", dict.GetValueOrDefault(fieldname).ClassProperty;
}
return sampleObject;
}
}
Trying to copy values from an existing NameValueCollection object to a Dictionary. I have the following code below to do that but seems the Add does not accept that my keys and values are as Strings
IDictionary<TKey, TValue> dict = new Dictionary<TKey, TValue>();
public void copyFromNameValueCollection (NameValueCollection a)
{
foreach (var k in a.AllKeys)
{
dict.Add(k, a[k]);
}
}
Note: NameValueCollection contains String keys and values and so I simply want to provide here a method to allow copying of those to a generic dictionary.
Extension method plus linq:
public static Dictionary<string, string> ToDictionary(this NameValueCollection nvc) {
return nvc.AllKeys.ToDictionary(k => k, k => nvc[k]);
}
//example
var dictionary = nvc.ToDictionary();
It doesn't make sense to use generics here since you can't assign strings to some arbitrary generic type:
IDictionary<string, string> dict = new Dictionary<string, string>();
public void copyFrom(NameValueCollection a)
{
foreach (var k in a.AllKeys)
{
dict.Add(k, a[k]);
}
}
although you should probably create a method to create a new dictionary instead:
public static IDictionary<string, string> ToDictionary(this NameValueCollection col)
{
IDictionary<string, string> dict = new Dictionary<string, string>();
foreach (var k in col.AllKeys)
{
dict.Add(k, col[k]);
}
return dict;
}
which you can use like:
NameValueCollection nvc = //
var dictionary = nvc.ToDictionary();
If you want a general way of converting the strings in the collection into the required key/value types, you can use type converters:
public static Dictionary<TKey, TValue> ToDictionary<TKey, TValue>(this NameValueCollection col)
{
var dict = new Dictionary<TKey, TValue>();
var keyConverter = TypeDescriptor.GetConverter(typeof(TKey));
var valueConverter = TypeDescriptor.GetConverter(typeof(TValue));
foreach(string name in col)
{
TKey key = (TKey)keyConverter.ConvertFromString(name);
TValue value = (TValue)valueConverter.ConvertFromString(col[name]);
dict.Add(key, value);
}
return dict;
}
parameters.AllKeys.ToDictionary(t => t, t => parameters[t]);
Use LINQ:
public static IDictionary<string, string> ToDictionary(this NameValueCollection collection)
{
return collection.Cast<string>().ToDictionary(k => k, v => collection[v]);
}
Usage:
IDictionary<string, string> dic = nv.ToDictionary();
Super-Short Version
var dataNvc = HttpUtility.ParseQueryString(data);
var dataCollection = dataNvc.AllKeys.ToDictionary(o => o, o => dataNvc[o]);
If you know that your dictionary is always going to contain strings, specify it to contain strings instead of making your class generic:
IDictionary<string, string> dict = new Dictionary<string, string>();
With this, things will "just work" as written (without the generic method specification).
If you need this to be a generic class, and hold generic data, you need some way to convert from string to TKey and string to TValue. You could provide delegates to your copy method to do this:
public void CopyFrom(NameValueCollection a, Func<string, TKey> keyConvert, Func<string, TValue> valueConvert)
{
foreach(var k in a.AllKeys)
{
dict.Add(keyConvert(k), valueConvert(a[k]));
}
}
You would then need to pass a delegate in that would perform the conversion from string to TValue and string to TKey.
You should not forget about EqualityComparer. But it is not a public property. So, you should use reflection to get it.
public static IEqualityComparer GetEqualityComparer(this NameObjectCollectionBase nameObjectCollection)
{
PropertyInfo propertyInfo = typeof(NameObjectCollectionBase).GetProperty("Comparer", BindingFlags.Instance | BindingFlags.NonPublic);
return (IEqualityComparer)propertyInfo.GetValue(nameObjectCollection);
}
public static IEqualityComparer<string> GetEqualityComparer(this NameValueCollection nameValueCollection)
{
return (IEqualityComparer<string>)((NameObjectCollectionBase)nameValueCollection).GetEqualityComparer();
}
public static Dictionary<string, string> ToDictionary(this NameValueCollection nameValueCollection)
{
Dictionary<string, string> dictionary =
nameValueCollection.AllKeys.ToDictionary(x => x, x => nameValueCollection[x], nameValueCollection.GetEqualityComparer());
return dictionary;
}
I'm newb with generics/iterators/enumerators etc.
I have code, it keeps field number (int) and error mesages (List string) for each field:
public class ErrorList : IEnumerable // ?
{
private Dictionary <int, List<string>> errorList;
// ...
}
How to make this class work with foreach loop? I wanna use GetEnumerator form Dictionary, but how should i do this?
You could simply provide a public GetEnumerator method:
public class ErrorList
{
private Dictionary<int, List<string>> errorList = new Dictionary<int, List<string>>();
... some methods that fill the errorList field
public IEnumerator<KeyValuePair<int, List<string>>> GetEnumerator()
{
return errorList.GetEnumerator();
}
}
and now assuming you have an instance of ErrorList:
var errors = new ErrorList();
you can loop through them:
foreach (KeyValuePair<int, List<string>> item in errors)
{
...
}
Dictionary implements IEnumerable<KeyValuePair<TKey, TValue>>, so this works:
foreach (KeyValuePair<Int, List<String>> kvp in errorList) {
var idx = kvp.Key;
var vals = kvp.Value;
// ... do whatever here
}
You can simply return errorList.GetEnumerator().
I have create a Class named "EngDictionary". and Then i define a dictionary in a function
e.g:
public void Dict()
{
Dictionary<string, string> d = new Dictionary<string, string>();
d.Add("Classifieds", "Kleinanzeigen");
//d.Add("windows", 5);
}
Now i want to access above defined dictionary from my main class for retrieving the keys and values of my Dictionary. Please Suggest me some code. I am using Visual C# 2008 Express Edition, Win Application
Declare Dictionary as class property.
public class Dict {
private Dictionary<string, string> dict;
public SomeDictionary { get dict; set dict = value; }
public Dict() {
dict = new Dictionary<string, string>();
dict.Add("Classifieds", "Kleinanzeigen");
}
}
In other class:
Dict d = new Dict();
string test = d.SomeDictionary["Classifieds"];
Console.WriteLine(test);
return the dictionary from the method.
public Dictionary<string, string> Dict() {.... ; return d;}
In your main class.
EngDictionary dict = new EngDictionary();
Dictionary<string, string> dictionary = dict.Dict();
You can declare Dictionary<string, string> d as a member variable of your class , and initialize this object in the class constructor.You can have a getter method to get the dictionary in other classes.
public class EngDictionary
{
Dictionary<string, string> dictionary;
public void EngDictionary()
{
dictionary = new Dictionary<string, string>();
dictionary.Add("Classifieds", "Kleinanzeigen");
....
}
public Dictionary<string, string> getDictionary()
{
return this.dictionary;
}
}
I have a class
public class Dict
{
public Dictionary<string, string> SomeDictionary { get; } = new Dictionary<string, string>()
{
{ "Classifieds", "Kleinanzeigen" }
};
}
then in any other class
Dict Dic = new Dict();
foreach (var item in Dic.SomeDictionary)
{
Console.WriteLine(item.Key);
Console.WriteLine(item.Value);
}
i seem to write this code over and over again and wanted to see if there was a better way of doing it more generically.
I start out with a list of Foo objects
Foo[] foos = GenerateFoos();
I think want to create a dictionary where the key and value are both properties of Foo
for example:
Dictionary<string, string> fooDict = new Dictionary<string, string>():
foreach (Foo foo in foos)
{
fooDict[foo.Name] = foo.StreetAddress;
}
is there anyway of writing this code generically as it seems like a basic template where there is an array of objects, a key property a value property and a dictionary.
Any suggestions?
I am using VS 2005 (C#, 2.0)
With LINQ:
var fooDict = foos.ToDictionary(x=>x.Name,x=>x.StreetAddress);
(and yes, fooDict is Dictionary<string, string>)
edit to show the pain in VS2005:
Dictionary<string, string> fooDict =
Program.ToDictionary<Foo, string, string>(foos,
delegate(Foo foo) { return foo.Name; },
delegate(Foo foo) { return foo.StreetAddress; });
where you have (in Program):
public static Dictionary<TKey, TValue> ToDictionary<TSource, TKey, TValue>(
IEnumerable<TSource> items,
Converter<TSource, TKey> keySelector,
Converter<TSource, TValue> valueSelector)
{
Dictionary<TKey, TValue> result = new Dictionary<TKey, TValue>();
foreach (TSource item in items)
{
result.Add(keySelector(item), valueSelector(item));
}
return result;
}
If you are using framework 3.5, you can use the ToDictionary extension:
Dictionary<string, string> fooDict = foos.ToDictionary(f => f.Name, f => f.StreetAddress);
For framework 2.0, the code is pretty much as simple as it can be.
You can improve the performance a bit by specifying the capacity for the dictionary when you create it, so that it doesn't have to do any reallocations while you fill it:
Dictionary<string, string> fooDict = new Dictionary<string, string>(foos.Count):
Without LINQ, no, there's no built-in helpers for this. You could write one though:
// I forget if you need this delegate definition -- this may be already defined in .NET 2.0
public delegate R Func<T,R>(T obj);
public static Dictionary<K,V> BuildDictionary<T,K,V>(IEnumerable<T> objs, Func<T,K> kf, Func<T,V> vf)
{
Dictionary<K,V> d = new Dictionary<K,V>();
foreach (T obj in objs)
{
d[kf(obj)] = vf(obj);
}
return d;
}
Dictionary<string, string> fooDict = BuildDictionary(foos, new Func<Foo,string>(delegate(Foo foo) { return foo.Name; }), new Func<Foo,string>(delegate(Foo foo) { return foo.StreetAddress; }));
It doesn't look nearly as elegant as the LINQ-based answers, does it...
Here's a solution that's .net 2.0 compatible that uses System.Web.UI.Databinder to do the reflection on the property name - you lose compile-time type checking.
public static Dictionary<string, string> ToDictionary<T>(List<T> list, string keyName, string valueName)
{
Dictionary<string, string> outputDictionary = new Dictionary<string, string>();
foreach (T item in list)
{
string key = Eval<T, string>(item, keyName);
string value = Eval<T, string>(item, valueName);
output[key] = value;
}
return outputDictionary;
}
public static TOut Eval<TIn, TOut>(TIn source, string propertyName)
{
object o = DataBinder.GetPropertyValue(source, propertyName);
if (o is TOut)
return (TOut)o;
return default(TOut);
}
You would call as follows:
Dictionary<string, string> fooDict = ToDictionary(foos, "Name", "StreetAddress");