How to Multiply and sum nested dictionary in C#? - c#

I have a Dictionary in C# with this structure :
Dictionary<int, Dictionary<string, double>> dictionary = new Dictionary<int, Dictionary<string, double>>
{
{
0, new Dictionary<string, double>
{
{ "eat",0.15 },
{ "food", 0.16 }
}
},
{
1, new Dictionary<string, double>
{
{ "eat",0.32 },
{ "food", 0.2 }
}
},
};
I want to sum and multiply eat in other dictionary,
0.15 * 0.32 + 0.16 * 0.2
what should i do to code this in c# with foreach?
thankyou

Here is a LINQ solution:
Dictionary<int, Dictionary<string, double>> dict = new Dictionary<int, Dictionary<string, double>>() {
{0,new Dictionary<string, double> { { "eat",0.15 }, { "food", 0.16 } } },
{1,new Dictionary<string, double> { { "eat",0.32 }, { "food", 0.2 } } }
};
double eat = dict.Values.Select(x => x["eat"]).Aggregate((x, y) => x * y);
double food = dict.Values.Select(x => x["food"]).Aggregate((x, y) => x * y);
double result = eat + food;
EDIT
Here is a more compact and universal solution:
var result = dict.SelectMany(x => x.Value)
.GroupBy(x => x.Key, y => y.Value, (Key, Value) => new { Value })
.Sum(x => x.Value.Aggregate((a, b) => a * b));
result = 0.08
DEMO HERE

You can do this
var dict = new Dictionary<int, Dictionary<string, double>>() {
{0, new Dictionary<string, double>() {{"eat", 0.15}, {"food", 0.16}}},
{1, new Dictionary<string, double>() {{"eat", 0.32}, {"food", 0.2}}}};
var total = dict.Values.SelectMany(x => x) // Flatten
.GroupBy(x => x.Key) // Group by key
.Sum(x => x.Select(y => y.Value) // sum list of sub values
.Aggregate((y, z) => y * z)); // multiply
Console.WriteLine(total);
Output
0.08
Full Demo here

You can solve this problem using foreach loop and some linq at the end as following:
Dictionary<int, Dictionary<string, double>> data = new Dictionary<int, Dictionary<string, double>>()
{
{
0,new Dictionary<string, double>(){{ "eat" , 0.15 },{ "food" , 0.16} }
},
{
1,new Dictionary<string, double>(){{ "eat" , 0.32 },{ "food" , 0.2 } }
}
};
Dictionary<string, double> finalResultDic = new Dictionary<string, double>();
foreach (var entry in data)
{
foreach (var subEntry in entry.Value)
{
if (finalResultDic.ContainsKey(subEntry.Key))
{
finalResultDic[subEntry.Key] *= subEntry.Value;
}
else
{
finalResultDic.Add(subEntry.Key, subEntry.Value);
}
}
}
var finalResult = finalResultDic.Sum(dic => dic.Value);

Try following :
Dictionary<int, Dictionary<string, double>> dict = new Dictionary<int,Dictionary<string,double>>() {
{0, new Dictionary<string,double>() {{"eat" , 0.15}, {"food" , 0.16}}},
{1, new Dictionary<string,double>(){{"eat", 0.32},{"food", 0.2}}}
};
double total = dict.Select(x => x.Value.Select(y => x.Key * y.Value).Sum()).Sum();

Related

Get Except of multiple nested dictionaries using LINQ expression

I want to get different of n numbers of dictionaries using a lambda expression:
Dictionary<string, string> d1 = new Dictionary<string, string>();
d1.Add("Joe", "2, Barfield Way");
d1.Add("Mike", "17, Apollo Avenue");
d1.Add("Jane", "69, Lance Drive");
Dictionary<string, string> d2 = new Dictionary<string, string>();
d2.Add("Joe", "2, Barfield Way");
d2.Add("Jane", "69, Lance Drive");
// var diff = d1.Except(d2);
Let say I want to get the difference of two above dictionaries var diff = d1.Except(d2);
Now I want to get the same out using lambda expression for N numbers of dictionaries.
For an instant, I have merged two dictionaries into one. I want to get a difference of two dictionaries using lambda expression or any other LINQ expression.
Dictionary<string, Dictionary<string, string>> d = new Dictionary<string, Dictionary<string, string>>();
d.Add("Test", d1);
d.Add("Test2", d2);
I have tried the expression below but could not get any results.
d.Select(c => c.Value.Except(c.Value))
You need some Linq methods:
var result = d.SelectMany(d => d.Value).GroupBy(c => c.Key)
.Where(c => c.Count() == 1).ToDictionary(t => t.Key, t => t.Select(c => c.Value)
.FirstOrDefault()).ToList();
Convert it to a collection of KeyValuePair<> enumerables and follow the same logic using .Aggregate()
var result = d.Select(x => x.Value.AsEnumerable()).Aggregate((x, y) => x.Except(y));
You can store the Dictionaries in a List<Dictionary<string, string>>.
Then query this collection and group by the keys , filter by count of key to get the unique ones only, then build a new Dictionary :
var d1 = new Dictionary<string, string>
{
{ "Joe", "2, Barfield Way" },
{ "Mike", "17, Apollo Avenue" },
{ "Jane", "69, Lance Drive" }
};
var d2 = new Dictionary<string, string>
{
{ "Joe", "2, Barfield Way" },
{ "foo", "bar" },
{ "Jane", "69, Lance Drive" }
};
var d3 = new Dictionary<string, string>
{
{ "hello", "world" },
{ "foo", "bar" }
};
var dicts = new List<Dictionary<string, string>>
{
d1,
d2,
d3
};
var distinct = dicts.SelectMany(d => d) // Flatten the collection of dictionaries
.GroupBy(d => d.Key) // Group the sequence by key
.Where(d => d.Count() == 1) // Filter the result for unique keys only
.ToDictionary(k => k.Key, v => v.Select(x => x.Value)
.First()); // Materialize the sequence in a Dictionary<string, string>
foreach (var key in distinct.Keys)
{
Console.WriteLine($"{key} -> {distinct[key]}");
}
Output is
Mike -> 17, Apollo Avenue
hello -> world
This way you will get the same result:
Dictionary<string, string> d1 = new Dictionary<string, string>();
d1.Add("Joe", "2, Barfield Way");
d1.Add("Mike", "17, Apollo Avenue");
d1.Add("Jane", "69, Lance Drive");
Dictionary<string, string> d2 = new Dictionary<string, string>();
d2.Add("Joe", "2, Barfield Way");
d2.Add("Jane", "69, Lance Drive");
var diff = d1.Except(d2);
Dictionary<string, Dictionary<string, string>> d = new Dictionary<string, Dictionary<string, string>>();
d.Add("Test", d1);
d.Add("Test2", d2);
var diff1 = d.SelectMany(x => x.Value).GroupBy(x => new { x.Key, x.Value }).Where(x => x.Count() == 1).SelectMany(x => x.AsEnumerable());

Transform Dictionary<string, int> to Dictionary<int, List<string>>

Q How can I most efficiently convert a Dictionary<string, int> to a Dictionary<int, List<string>>?
Example
var input = new Dictionary<string, int>() { {"A", 1}, {"B", 1}, {"C", 2} ...
Dictionary<int, List<string>> result = Transform(input)
Assert.IsTrue(result, { {1, {"A", "B"}}, {2, {"C"}} ... });
Group the dictionary by values and map the group keys to list of keys:
input.GroupBy(x => x.Value).ToDictionary(x => x.Key, x => x.Select(_ => _.Key).ToList())
How about this?
var result =
dict.ToLookup(x => x.Value, x => x.Key)
.ToDictionary(y => y.Key, y => y.ToList());
Although I don't see why you couldn't just use the result from dict.ToLookup() without changing it to a dictionary, for example:
var dict = new Dictionary<string, int>
{
{"One", 1},
{"Two", 2},
{"1", 1},
{"TWO", 2},
{"ii", 2}
};
var test = dict.ToLookup(x => x.Value, x => x.Key);
Console.WriteLine(string.Join(", ", test[2])); // Prints: Two, TWO, ii
You can use Linq to achieve.
private static Dictionary<int, List<string>> Transform(Dictionary<string, int> input)
{
var result = new Dictionary<int, List<string>>();
foreach (var value in input.Select(x => x.Value).Distinct())
{
var lst = input.Where(x => x.Value == value).Select(x => x.Key).ToList();
result.Add(value, lst);
}
return result;
}

C# List<Dictionary<string,string>> - how to extract unique key/value pairs

In a C# List>, how can I extract unique key/value pairs and store it in List>?
List<Dictionary<string,string>> md = new List<Dictionary<string,string>>();
Input
md[0] :
[0]:"A","Apple"
[1]:"B","Ball"
md[1]:
[0]:"A","Apple"
[1]:"B","Ball"
md[2]:
[0]: "C", "Cat"
[1]: "D", "Dog"
Output
md[0] :
[0]:"A","Apple"
[1]:"B","Ball"
md[1]:
[0]:"C" : "Cat"
[1]:"D" : "Dog"
Code sample to extract both unique key/value pairs are needed, only unique keys or unique values are not needed.
(* Note : [0],[1] above depicts the indexes in the list and dictionary and not the keys or values)
List<Dictionary<string,string>> md = new List<Dictionary<string,string>>();
var unique = new Dictionary<string, string>();
foreach (var m in md)
{
foreach(var innerKey in m.Key)
{
if (!unique.ContainsKey(innerKey))
{
unique.Add(innerKey, m[innerKey]);
}
}
}
One possible strictly correct solution would be to implement IEqualityComparer<Dictionary<string, string>>:
public class DictionaryComparer : IEqualityComparer<Dictionary<string, string>>
{
public int GetHashCode(Dictionary<string, string> d)
{
var hashCode = 17;
foreach (var entry in d.OrderBy(kvp => kvp.Key))
{
hashCode = hashCode * 23 + entry.Key.GetHashCode();
hashCode = hashCode * 23 + entry.Value.GetHashCode();
}
return hashCode;
}
public bool Equals(Dictionary<string, string> d1, Dictionary<string, string> d2)
{
string value2;
return d1.Count == d2.Count && d1.All(kvp => d2.TryGetValue(kvp.Key, out value2) && kvp.Value == value2);
}
}
Then to get your list of unique dictionaries:
var result = md.Distinct(new DictionaryComparer()).ToList();
You can do it with linq.
List<Dictionary<string, string>> md = new List<Dictionary<string, string>>();
md.Add(new Dictionary<string, string>() { { "A","Apple"}, { "B", "Ball" } });
md.Add(new Dictionary<string, string>() { { "A","Apple"}, { "B", "Ball" } });
md.Add(new Dictionary<string, string>() { { "C","Cat"}, { "D", "Dog" } });
var filtered =
md.GroupBy(x => string.Join("", x.Select(i => string.Format("{0}{1}", i.Key, i.Value)))).Select(x => x.First());
Variable "filtered" contains list of dictionaries with unique sets.

How to join two dictionaries?

I have two dictionaries. If the values in dict2 are same then we have to add the values for the matching keys from dict1 and generate a result in the result dictionary as given below.
**dict1** **dict2**
Id value Id value
24379 348 24379 270451
24368 348 24368 270451
24377 90 24377 270450
24366 90 24366 270450
24369 10 24369 270450
24300 25
Result:
24379 696
24368 696
24377 190
24366 190
24369 190
I have the following logic and would like to optimize this solution:
Dictionary<int, int> result = new Dictionary<int, int>();
foreach (int itemKey in dict1.keys)
{
result.add (itemKey, dict1.Where(a => dict2.ContainsKey(a.key)
&& dict2.ContiansKey(itemKey)
&& dict2[a.key] == dict2[itemKey])
.Sum(a => a.value);
}
You can do it in two steps:
Prepare a dictionary for looking up the value by dict2's value
Walk through dict1, and insert values from the look-up dictionary
Here is how you can do it:
var lookup = dict1
.Where(p => dict2.ContainsKey(p.Key))
.GroupBy(p => dict2[p.Key])
.ToDictionary(g => g.Key, g => g.Sum(p => p.Value));
var res = dict1.Keys
.Where(k => dict2.ContainsKey(k))
.ToDictionary(k => k, k => lookup[dict2[k]]);
Demo.
public static void DicAddTest()
{
Dictionary<int, int> dic1 = new Dictionary<int, int>() { {24379,348}, { 24368, 348 }, { 24377, 90 }, { 24366, 90 } };
Dictionary<int, int> dic2 = new Dictionary<int, int>() { { 24379, 270451 }, { 24368, 270451 }, { 24377, 270450 }, { 24366, 270450 } };
Dictionary<int, int> dicResult = DicAdd(dic1, dic2);
foreach (KeyValuePair<int, int> kvp in dicResult)
Debug.WriteLine("{0} {1}", kvp.Key, kvp.Value);
Debug.WriteLine("");
}
public static Dictionary<int, int> DicAdd(Dictionary<int, int> dic1, Dictionary<int, int> dic2)
{
Dictionary<int, int> dicResult = new Dictionary<int, int>(dic1);
foreach (int k in dic1.Keys.Where(x => dic2.Keys.Contains(x)))
dicResult[k] = dicResult[k] + dicResult[k];
return dicResult;
}
question is not clear
public static Dictionary<int, int> DicAdd2(Dictionary<int, int> dic1, Dictionary<int, int> dic2)
{
Dictionary<int, int> dicResult = new Dictionary<int, int>();
foreach (KeyValuePair<int, int> kvp in dic1.Where(x => dic2.Keys.Contains(x.Key)))
dicResult.Add(kvp.Key, 2 * kvp.Value);
return dicResult;
}
Perhaps it's easier to do like this, if you are not sure that dict1 and dict2 will have the same keys:
var result = new Dictionary<int, int>();
foreach(var kvp in dict1)
{
int value;
if(dict2.TryGetValue(kvp.Key, out value))
{
result[kvp.Key] = kvp.Value * 2;
}
}
This will only add values present in both dictionaries. If your Dictionary is very big, you could perhaps use a Parallel For, or consider use Hashtable instead.

A library like Python's collections.Counter library for C# -> Getting the difference of values between two dictionary objects in C#

This is how I would create a Dictionary in C#.
Dictionary<string, int> d = new Dictionary<string, int>()
{
{"cheese", 2},
{"cakes", 1},
{"milk", 0},
{"humans", -1} // This one's for laughs
};
In Python if you have a dictionary like so:
from collections import Counter
my_first_dict = {
"cheese": 1,
"cakes": 2,
"milk": 3,
}
my_second_dict = {
"cheese": 0,
"cakes": 1,
"milk": 4,
}
print Counter(my_first_dict) - Counter(my_second_dict)
>>> Counter({'cheese': 1, 'cakes': 1})
As you can see, Counter is very useful when comparing dictionary objects.
Is there a library in C#, that will allow me to do something similar to this, or do I have to code it from scratch?
You can join the two dictionaries together and then create a new one based on the given operation with only a few lines of code:
Dictionary<string, int> d1 = new Dictionary<string, int>();
Dictionary<string, int> d2 = new Dictionary<string, int>();
var difference = d1.Join(d2, pair => pair.Key, pair => pair.Key, (a, b) => new
{
Key = a.Key,
Value = a.Value - b.Value,
})
.Where(pair => pair.Value > 0)
.ToDictionary(pair => pair.Key, pair => pair.Value);
There is no system class that you've shown that wraps a dictionary an provides a - operator for them, but you can make your own if you want easily enough:
public class Counter<T> : IEnumerable<KeyValuePair<T, int>>
{
private IEnumerable<KeyValuePair<T, int>> sequence;
public Counter(IEnumerable<KeyValuePair<T, int>> sequence)
{
this.sequence = sequence;
}
public static Counter<T> operator -(Counter<T> first, Counter<T> second)
{
return new Counter<T>(first.Join(second
, pair => pair.Key, pair => pair.Key, (a, b) =>
new KeyValuePair<T, int>(a.Key, a.Value - b.Value))
.Where(pair => pair.Value > 0));
}
public IEnumerator<KeyValuePair<T, int>> GetEnumerator()
{
return sequence.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
There's no built-in functionality like this, but you can use a bit of Linq:
Dictionary<string, int> first = new Dictionary<string, int>()
{
{"cheese", 1},
{"cakes", 2},
{"milk", 3},
};
Dictionary<string, int> second = new Dictionary<string, int>()
{
{"cheese", 0},
{"cakes", 1},
{"milk", 4},
};
var results =
(from x in first
join y in second on x.Key equals y.Key
where x.Value - y.Value > 0
select new { x.Key, Value = x.Value - y.Value })
.ToDictionary(p => p.Key, p => p.Value);
// returns a dictionary like { { "cheese", 1 }, { "cakes", 1 } }

Categories

Resources