I'm comparing two List<Dictionary<string, object>> with my own IEqualityComparer<Dictionary<string, object>> implementation, but neither GetHashCode nor Equals method get called.
Here's my own IEqualityComparer implementation.
public class TestEqualityComparer : IEqualityComparer<Dictionary<string, object>>
{
public bool Equals(Dictionary<string, object> a, Dictionary<string, object> b)
{
return true; // breakpoint here
}
public int GetHashCode(Dictionary<string, object> obj)
{
return 0; // breakpoint here
}
}
And here's a actual comparing code.
var a = new List<Dictionary<string, object>>();
var b = new List<Dictionary<string, object>>();
a.Add(new Dictionary<string, object> { ["id"] = 1, ["msg"] = "aaaaa" });
a.Add(new Dictionary<string, object> { ["id"] = 2, ["msg"] = "bbbbb" });
a.Add(new Dictionary<string, object> { ["id"] = 3, ["msg"] = "ccccc" });
b.Add(new Dictionary<string, object> { ["id"] = 1, ["msg"] = "zzzzz" });
b.Add(new Dictionary<string, object> { ["id"] = 2, ["msg"] = "bbbbb" });
b.Add(new Dictionary<string, object> { ["id"] = 4, ["msg"] = "ddddd" });
var except = a.Except(b, new TestEqualityComparer());
When I ran the above code, breakpoints never got triggered.
What's the problem?
Since LINQ uses deferred execution the contents of except collection will not be determined unless you decide to iterate over it, hence no calls to your IEqualityComparer.
To force evaluation of your Except statement you can either iterate over it with foreach or append ToList/ToArray to your statement, like so:
var except = a.Except(b, new TestEqualityComparer()).ToList(); // ToList forces processing of LINQ query
Related
I have 4 dictionary, each contain a button's name and the button's value.
I Have a List that contain the name of each dictionary
private Dictionary<string, int> TableArray = new Dictionary<string, int>() { { "ButtonRMT35", 35 }, { "ButtonRMT17", 17 }, { "ButtonRMT11", 11 }, { "ButtonRMT8", 8 }, { "ButtonRMT5", 5 } };
private Dictionary<string, int> ParArray = new Dictionary<string, int>() { { "ButtonRMP20", 20 }, { "ButtonRMP15", 15 }, { "ButtonRMP10", 10 }, { "ButtonRMP5", 5 } };
private Dictionary<string, int> MaxChipsRPArray = new Dictionary<string, int>() { { "ButtonRPC20", 20 }, { "ButtonRPC15", 15 }, { "ButtonRPC10", 10 }, { "ButtonRPC5", 5 } };
private Dictionary<string, int> QuestionSerieRPArray = new Dictionary<string, int>() { { "ButtonRPQ20", 20 }, { "ButtonRPQ15", 15 }, { "ButtonRPQ10", 10 }, { "ButtonRPQ5", 5 } };
public List<string> DictionaryList = new List<string>() { "TableArray", "ParArray", "MaxChipsRPArray", "QuestionSerieRPArray" };
I would like to do something like that
foreach (var dictionnary in DictionaryList)
{
foreach (var buttonName in dictionnary.Keys)
{
DoSomething();
}
}
Is there a way to do that?
The List<string> (DictionaryList) contains strings. Those strings are not variable identifiers (variable identifiers are not the same as C#/.NET strings; variable identifiers are lexical tokens in the C# language, being parsed by the C# compiler during the build of your program), and thus cannot be used to refer to some variable.[1]
Rather than maintaining strings in your DictionaryList, let it maintain the dictionaries itself:
private Dictionary<string, int> TableArray = ...
private Dictionary<string, int> ParArray = ...
private Dictionary<string, int> MaxChipsRPArray = ...
private Dictionary<string, int> QuestionSerieRPArray = ...
public List<Dictionary<string, int>> DictionaryList = new List<Dictionary<string, int>>()
{
TableArray, ParArray, MaxChipsRPArray, QuestionSerieRPArray
};
If you need to access the dictionaries by some name provided as a string (regardless whether that name would correlate with the variable/field names) you can turn the list into a dictionary of dictionaries (mapping some name to each of your dictionaries) instead:
private Dictionary<string, int> TableArray = ...
private Dictionary<string, int> ParArray = ...
private Dictionary<string, int> MaxChipsRPArray = ...
private Dictionary<string, int> QuestionSerieRPArray = ...
public Dictionary<string, <Dictionary<string, int>>> Dictionaries =
new Dictionary<string, <Dictionary<string, int>>>()
{
["TableArray"] = TableArray,
["MaxChipsRPArray"] = MaxChipsRPArray,
["QuestionSerieRPArray"] = QuestionSerieRPArray
};
...
foreach (var dictionary in Dictionaries.Values)
{
foreach (var buttonName in dictionary.Keys)
{
DoSomething();
}
}
You could then access an individual dictionary by name through the public Dictionaries field like this, for example:
var someDictionaryIWant = Dictionaries["MaxChipsRPArray"];
foreach (var buttonName in someDictionaryIWant.Keys)
{
DoSomething();
}
[1] I just told a grey lie here. For fields and properties, it would be possible to access fields/properties by their field/property name given as a string through a mechanism called "reflection". But reflection is cumbersome (likely even complicated for inexperienced programmers), slow, does not play well with trimming or compiling into native code, is normally not applicable to local variables declared inside methods, etc... But i think it's doubtful that you are looking for some dirty hack-ish way to solve your problem when there are cleaner and more straightforward solutions to your problem.
You are on a right track, however it would be hard to achieve by using variable names.
Use nested list, like this: List<Dictionary<string, int>> dictionaryList
Then add your dictionaries to the list, and iterate over them in the for each loop like you initially wanted to.
I would like to simplify below nested foreach loops using LINQ but couldn't figure out the way. I guess I can use SelectMany using lambda but not sure. I want to create list of objects of ClassA after this nested iteration. Any help is appreciated:
public List<ClassA> GetLists(Dictionary<string, Dictionary<IEnumerable, Dictionary<string, ClassB>>> groups)
{
var retOutput = new List<ClassA>();
foreach (KeyValuePair<string, Dictionary<IEnumerable, Dictionary<string, ClassB>>> group1 in groups)
{
foreach (KeyValuePair<IEnumerable, Dictionary<string, ClassB>> group2 in group1.Value)
{
foreach (KeyValuePair<string, ClassB> group3 in group2.Value)
{
GetList(retOutput, group1.Key,
group2.Key,
group3);
}
}
}
return retOutput;
}
private static void GetList(List<ClassA> retOutput,
string group1Key,
IEnumerable group2Key,
KeyValuePair<string, ClassB> group3)
{
List<List<string>> itemIdsLists = group3.Value.ItemId.IntoChunks(2000);
foreach (var itemIdList in itemIdsLists)
{
var currentRequest = new ClassA
{
TransactionType = group1Key,
Filters = new Dictionary<string, object>(),
ItemIds = new List<string>(),
PropStreamsDict = new Dictionary<string, Tuple<long, string>>()
};
if (group2Key is Dictionary<string, object>)
{
currentRequest.Filters = (Dictionary<string, object>)group2Key;
}
currentRequest.PropStreamsDict.Add(group3.Key, Tuple.Create(group3.Value.StreamId,
group3.Value.Uom));
currentRequest.ItemIds.AddRange(itemIdList);
retOutput.Add(currentRequest);
}
}
You should use SelectMany to make nested foreach.
Here what I come up with:
public List<ClassA> GetLists(Dictionary<string, Dictionary<IEnumerable, Dictionary<string, ClassB>>> groups)
{
return groups
.SelectMany(grp1 => grp1.Value
.SelectMany(grp2 => grp2.Value
.SelectMany(grp3 => grp3.Value.ItemId
.IntoChunks(2000)
.Select(itemIdList =>
new ClassA
{
TransactionType = grp1.Key,
Filters = grp2.Key is Dictionary<string, object> ?
(Dictionary<string, object>)grp2.Key :
new Dictionary<string, object>(),
ItemIds = new List<string>(itemIdList),
PropStreamsDict = new Dictionary<string, Tuple<long, string>>
{
{ grp3.Key, Tuple.Create(grp3.Value.StreamId, grp3.Value.Uom) }
}
}
)
)
)
)
.ToList();
}
You didn't post your ClassA and ClassB so I had to guess.
I have created a method that inspects an object and returns a [requested] set of properties.
public static List<object> Inspect<T>(T obj, params Func<T, object>[] funcs)
{
List<object> results = new List<object>(funcs.Length);
foreach (var func in funcs)
{
results.Add(func(obj));
}
return results;
}
It is then invoked, for example on a List, like so:
List<string> peopleData = new List<string>(10) { "name", "age", "address" };
List<object> properties = Inspect(peopleData, p => p.Count, p => p.Capacity);
// The results would be
// properties[0] = 3
// properties[1] = 10
I would like to adapt the Inspect method to instead return a Dictionary<string, object>, where the keys of the dictionary would be the property names. The adapted method would then be invoked like this:
List<string> peopleData = new List<string>(10) { "name", "age", "address" };
Dictionary<string, object> properties = Inspect(peopleData, p => p.Count, p => p.Capacity);
// The results would be
// properties["Count"] = 3
// properties["Capacity"] = 10
Is this possible? If so, and if the solution is reflection-based (as I assume it'd have to be), would there be a big performance hit?
You'd have to use the classic "interrogation" approach for Func<..> - Retrieving Property name from lambda expression
public static IDictionary<string, object> Inspect<T>(T obj,
params Expression<Func<T, object>>[] funcs)
{
Dictionary<string, object> results = new Dictionary<string, object>();
foreach (var func in funcs)
{
var propInfo = GetPropertyInfo(obj, func)
results[propInfo.Name] = func.Compile()(obj));
}
return results;
}
Ps, as Servy pointed out, you'd also need to make the params use Expression.
I have a Dictionary<string,int> dictionary1 and I need to convert it into a List<Data> where Data has the properties lable = dictionary1.key and value = dictionary1.value. I don't want to use a for/foreach loop (written by myself) because in order to avoid it I am trying to use a Dictionary.
Another option would be having two different dictionaries (dictionary2 and dictionary3) where dictionary2<string,keyOfDictionary1> and dictionary3<string,valueOfDictionary1>.
Do I make sense? Is that possible? Is there a better option?
Assuming:
class Data
{
public string Label { get; set; }
public int Value { get; set; }
}
Then:
Dictionary<string, int> dic;
List<Data> list = dic.Select(p => new Data { Label = p.Key, Value = p.Value }).ToList();
Perhaps you could use LINQ?
dictionary1.Select(p => new Data(p.Key, p.Value)).ToList()
This is however using yield and thus loops in the background...
myDictionary.Select(x => new Data(){ label = x.Key, value = x.Value).ToList();
I assume that "no loop" actually means "i want LINQ":
List<Data> = dictionary1.Select(
pair => new Data() {
label = pair.Key,
value = pair.Value
})).ToList();
public class Data
{
public string Key { get; set; }
public int Value { get; set; }
}
private static void Main(string[] args)
{
Dictionary<string, int> dictionary1 = new Dictionary<string, int>();
dictionary1.Add("key1", 1);
dictionary1.Add("key2", 2);
List<Data> data = dictionary1.Select(z => new Data { Key = z.Key, Value = z.Value }).ToList();
Console.ReadLine();
}
Try
dictionary1.Select(p => new Data(p.Key, p.Value)).ToList();
.NET already has a data type that does what Data would do: KeyValuePair<T1,T2>. Dictionary already implements IEnumerable<KeyValuePair<T1,T2>>, just cast to it.
Dictionary<string, int> blah = new Dictionary<string, int>();
IEnumerable<KeyValuePair<string, int>> foo = blah;
This is a old post, but post only to help other persons ;)
Example to convert any object type:
public List<T> Select<T>(string filterParam)
{
DataTable dataTable = new DataTable()
//{... implement filter to fill dataTable }
List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
Dictionary<string, object> row;
foreach (DataRow dr in dataTable.Rows)
{
row = new Dictionary<string, object>();
foreach (DataColumn col in dataTable.Columns)
{
row.Add(col.ColumnName, dr[col]);
}
rows.Add(row);
}
string json = new JavaScriptSerializer().Serialize(rows);
using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(T[]));
var tick = (T[])deserializer.ReadObject(stream);
return tick.ToList();
}
}
Just in case just helps anyone, I did it like this - will handle objects more complex than a single value type, as stated by the OP.
// Assumes: Dictionary<string, MyObject> MyDictionary;
List<MyObject> list = new List<MyObject>();
list.AddRange(MyDictionary.Values.ToArray());
As i know, the method to add values for dictionary as below.
Dictionary<string, string> myDict = new Dictionary<string, string>();
myDict.Add("a", "1");
If I declared "myDictDict" as the style below.
IDictionary<string, Dictionary<string, string>> myDictDict = new Dictionary<string, Dictionary<string, string>>();
myDictDict .Add("hello", "tom","cat"); ?// How to add value here.
thank you.
The proper way is like this:
// myDictDict is Dictionary<string, Dictionary<string, string>>
Dictionary<string, string> myDict;
string key = "hello";
if (!myDictDict.TryGetValue(key, out myDict)) {
myDict = new Dictionary<string, string>();
myDictDict.Add(key, myDict);
}
myDict.Add("tom", "cat");
This will extract the dictionary corresponding to the key (hello in your example) or create it if necessary and then will add the key/value pair to that dictionary. You could even extract this into an extension method.
static class Extensions {
public static void AddToNestedDictionary<TKey, TNestedDictionary, TNestedKey, TNestedValue>(
this IDictionary<TKey, TNestedDictionary> dictionary,
TKey key,
TNestedKey nestedKey,
TNestedValue nestedValue
) where TNestedDictionary : IDictionary<TNestedKey, TNestedValue> {
dictionary.AddToNestedDictionary(
key,
nestedKey,
nestedValue,
() => (TNestedDictionary)(IDictionary<TNestedKey, TNestedValue>)
new Dictionary<TNestedKey, TNestedValue>());
}
public static void AddToNestedDictionary<TKey, TNestedDictionary, TNestedKey, TNestedValue>(
this IDictionary<TKey, TNestedDictionary> dictionary,
TKey key,
TNestedKey nestedKey,
TNestedValue nestedValue,
Func<TNestedDictionary> provider
) where TNestedDictionary : IDictionary<TNestedKey, TNestedValue> {
TNestedDictionary nested;
if (!dictionary.TryGetValue(key, out nested)) {
nested = provider();
dictionary.Add(key, nested);
}
nested.Add(nestedKey, nestedValue);
}
}
I left out guarding against null input to keep the idea clear.
Usage:
myDictDict.AddToNestedDictionary(
"hello",
"tom",
"cat",
() => new Dictionary<string, string>()
);
or
myDictDict.AddToNesteDictionary("hello", "tom", "cat");
IDictionary<string,Dictionary<string,string>> myDictDict = new Dictionary<string,Dictionary<string,string>>();
Dictionary<string,string> dict = new Dictionary<string, string>();
dict.Add ("tom", "cat");
myDictDict.Add ("hello", dict);
You can use C# 3's collection initializers, like this:
IDictionary<string, Dictionary<string, string>> myDictDict = new Dictionary<string, Dictionary<string, string>> {
{ "hello", new Dictionary<string, string> { "Tom", "Cat" } }
};
If the dictionary already exists, you can write
dict.Add("hello", new Dictionary<string, string> { "Tom", "Cat" });
Note that this will only work if hello isn't an existing key in the outer dictionary. If it might be, you should use Jason's answer.
To handle this the "simple" way : something like this :
myDictDict.Add("some string", new Dictionary<string, string>());
myDictDict["some string"].Add("another", "string");
To respond directly to the OP's test case : (note the edit added below reflects a desire to correct the syntax of SLaks's answer : code tested and validated against Framework 3.5 Client profile in VS 2010 Beta 2)
// a simple case of creating an instance of a dictionary
// of type <string, string>
// and using .NET 3.0's (FrameWork => 3.5) collection initializer syntax
Dictionary<string, string> twoStringDict = new Dictionary<string, string>()
{
{"key one", "value one"},
{"key two", "value two"}, // note : an "extra" comma does not cause an error here
};
// more complex case as in the question on StackOverFlow
// where dictionary is type <string, Dictionary<string, string>>
// and using .NET 3.0's (FrameWork => 3.5) collection initializer syntax
Dictionary<string, Dictionary<string, string>> myDictDict = new Dictionary<string, Dictionary<string, string>>()
{
{ "key one",
new Dictionary<string, string>() { { "innerKeyOne", "innerValueOne" }}},
{ "key two",
new Dictionary<string, string>() { { "innerKeyTwo", "innerValueTwo" }}}
};
// syntax for adding another key value pair to the complex case
myDictDict.Add("key three", new Dictionary<string, string>() { { "innerKeyThree", "innerValueThree" }});
IDictionary<string, Dictionary<string, string>> myDictDict = new Dictionary<string, Dictionary<string, string>>();
var subDict = new Dictionary<string, string>();
myDictDict .Add("hello", subDict );
subDict.Add("tom", "cat");
You can define an extension method like this :
static void Add(this IDictionary<string, Dictionary<string, string>> dict, string a, string b, string c){
dict.Add(a, new Dictionary<string,string>(){{b,c}};
}
and then use it as :
myDictDict.Add("hello", "tom","cat");