I have the following
Dictionary<string,string> dict1 has 3 items
"A"="1.1"
"B"="2.1"
"C"="3.1"
Dictionary<string,string> dict2 has 3 items
"A"="1.2"
"B"="2.2"
"C"="3.2"
Dictionary<string,string> dict2 has 3 items
"A"="1.3"
"B"="2.3"
"C"="3.3"
I want a final Dict dictFinal which is of type Dictionary<string,string[]>
"A"="1.1,1.2,1.3"
"B"="2.1,2.2,2.3"
"C"="3.1,3.2,3.3"
Given similar keys, provide a collection of all the dictionaries and use SelectMany to handle a dynamic number of array items:
var dictionaries = new[] { dict1, dict2, dict3 };
var result = dictionaries.SelectMany(dict => dict)
.GroupBy(o => o.Key)
.ToDictionary(g => g.Key,
g => g.Select(o => o.Value).ToArray());
The dictionaries type could be a List<T> not necessarily an array as above. The important thing is that you group them together in a collection in order to LINQ over them.
Assuming all 3 dictionaries have the same keys, the following should do the job:
var d1 = new Dictionary<string, string>()
{
{"A", "1.1"},
{"B", "2.1"},
{"C", "3.1"}
};
var d2 = new Dictionary<string, string>()
{
{"A", "1.2"},
{"B", "2.2"},
{"C", "3.2"}
};
var d3 = new Dictionary<string, string>()
{
{"A", "1.3"},
{"B", "2.3"},
{"C", "3.3"}
};
var result = d1.Keys.ToDictionary(k => k, v => new[] {d1[v], d2[v], d3[v]});
Assuming all have the same keys the most straigt forward way is:
Dictionary<string,string[]> result = new Dictionary<string,string[]>();
foreach(var key in dict1.Keys)
{
result[key] = new string[]{dict1[key], dict2[key], dict3[key]};
}
Related
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());
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;
}
I would like to find all the occurances of my source list in my dictionary.
Currently, I'm looping through my dictionary, and comparing each value of dictionary.
Dictionary<string, list<int>> refList.
List<int> sourceList.
foreach(KeyValuePair<string, List<int>> kvp in refDict)
{
List<int> refList = (List<int>)kvp.Value;
bool isMatch = (refList.Count == sourceList.Count && refList.SequenceEqual(sourceList));
if (isMatch)
{
......
......
}
}
I would like to find the indexes in my dict of all the occurances of my source list.
I do not understand why you need a position (not an index!) of dictionary items because order of items is non deterministic, MSDN:
For purposes of enumeration, each item in the dictionary is treated as
a KeyValuePair structure representing a value and its
key. The order in which the items are returned is undefined.
but anyways:
Prepare data:
IDictionary<string, List<int>> refDict = new Dictionary<string, List<int>>
{
{"item1", new List<int> {1, 2, 3}},
{"item2", new List<int> {4, 5, 6}},
{"item3", new List<int> {1, 2, 3}}
};
List<int> sourceList = new List<int> {1, 2, 3};
Search for indexes:
var indexes = refDict.Values
.Select((list, index) => list.SequenceEqual(sourceList) ? index : -1)
.Where(x => x >= 0);
Search for keys:
var keys = refDict
.Where(item => item.Value.SequenceEqual(sourceList))
.Select(item => item.Key);
var list = new List<int> { 1,2,3 };
var dico = new Dictionary<string, List<int>>();
dico.Add("A", list);
dico.Add("B", new List<int> { 2,3 });
dico.Add("C", new List<int> { 1,2,3 });
var keys = dico.Where (d => d.Value.SequenceEqual(list)).Select (d => d.Key);
Pay attention that this wil return "A" and "C" !!!
Any cool quick ways to take two dictionaries to create a third that maps the key of the first to the value of the second in an inner-join style?
Dictionary<A,B> dic1 = new Dictionary<A,B> {{a1,b1},{a2,b2},{a3,b3}};
Dictionary<B,C> dic2 = new Dictionary<B,C> {{b1,c1},{b2,c2},{b4,c4}};
Dictionary<A,C> dic3 = SomeFunction(dic1,dic2);
// dic3 = {{a1,c1},{a2,c2}}
You could do something like this to join on the inner value
Dictionary<int, string> first = new Dictionary<int, string> { {1, "hello"}, {2, "world"}};
Dictionary<string, bool> second =
new Dictionary<string, bool> { { "hello", true }, {"world", false}};
var result = (from f in first
join s in second on f.Value equals s.Key
select new { f.Key, s.Value }).ToDictionary(x => x.Key, y => y.Value);
If you dump out result you'll see it is a Dictionary with the value {1: true, 2: false}
try this -
Dictionary<string, string> a, b, c;
//code to initialize the 3 dictionaries. a,b are original dictionaries and c is the new dictionary
c = ( from ak in a.Keys
where b.ContainsKey( ak )
select new KeyValuePair<string, string>( ak, b[ ak ] ) ).ToDictionary( d => d.Key, d=> d.Value );
Maybe something with ToDictionary
dic1.Where(d1=>dic2.ContainsKey(d1.Value)).ToDictionary(d1=>d1.Key,d1=>dic2[d1.Value]);
Dictionary<int, string> dic1 = new Dictionary<int,string>();
Dictionary<string, decimal> dic2 = new Dictionary<string,decimal>();
dic1.Add(1, "one");
dic1.Add(2, "two");
dic1.Add(3, "three");
dic1.Add(4, "four");
dic1.Add(5, "five");
dic2.Add("one",1.0m);
dic2.Add("two", 2.0m);
dic2.Add("three", 3.0m);
dic2.Add("four", 4.0m);
dic2.Add("five", 5.0m);
Dictionary<int, decimal> result = (from d1 in dic1
from d2 in dic2
where d1.Value == d2.Key
select new { d1.Key, d2.Value }).ToDictionary(p=>p.Key, p=>p.Value);
public Dictionary<A,C> SomeFunction(dic1, dic2)
{
var dic3 = new Dictionary<A,C>();
foreach (var item in dic1)
{
var item2 = dic2.Where(m=>m.Key == item.Value).FirstOrDefault();
if (item2 != null)
{
dic3.Add(item.Key, item2.Value);
}
}
return dic3
}
I believe this will work for what you want
public IDictionary<A, C> SomeFunction<A, B, C>(IDictionary<A, B> dic1, IDictionary<B, C> dic2)
{
var dic3 = new Dictionary<A, C>();
foreach (var item in dic1)
{
var a = item.Key;
var b = item.Value;
if (dic2.ContainsKey(b))
{
var c = dic2[b];
dic3.Add(a, c);
}
}
return dic3;
}
Handles the case of dic2 not containing keys corresponding to dic1s value without fake null values being stored, and IMO is pretty clear. I do like some LINQ, but I thought I'd give a procedural answer for once...
The simplest solution:
var dict3 = dict1.ToDictionary(p => p.Key, p => dict2[p.Value]);
Please, help minimize the following code:
There is a class with dictionary property:
class Foo
{
public int Field { get; set; }
public Dictionary<int, bool> dic { get; set; }
}
And a list of Foo instances. I want to get united dictionary from all class instances like that:
...
var items = new List<Foo>
{
new Foo {Field = 1, Dic = new Dictionary<int, bool> {{1, true}, {2, false}}},
new Foo {Field = 2, Dic = new Dictionary<int, bool> {{3, true}, {2, false}}}
};
var result = new Dictionary<int, bool>();
foreach (var dics in items.Select(x => x.Dic))
foreach (var pair in dics)
if (!result.ContainsKey(pair.Key))
result.Add(pair.Key, pair.Value);
// testing output
foreach (var pair in result)
Console.WriteLine("{0}, {1}", pair.Key, pair.Value);
Is it possible to do this with pure LINQ approach?
Thank you in advance!
You can use SelectMany to grab and flatten the inner dictionary elements:
var result = items.SelectMany(f => f.Dic)
.GroupBy(pair => pair.Key)
.ToDictionary(g => g.Key, g => g.First().Value);
edit: If you're feeling brave, this can be improved even further by picking up the DistinctBy method from Jon Skeet's morelinq project. Essentially, the GroupBy step is actually overkill, since all we really want is the first value for each key. If we select only the pairs with distinct keys, we can avoid the grouping and subsequent First call, like so:
var result = items.SelectMany(f => f.Dic)
.DistinctBy(pair => pair.Key)
.ToDictionary(pair => pair.Key, pair => pair.Value);
var result =
(from item in items
from pair in item.Dic
group pair by pair.Key
).ToDictionary(g => g.Key, g => g.First().Value);
I don't know if Distinct is better but it is shorter to write.
var result = items.SelectMany(d => d.Dic)
.Distinct()
.ToDictionary(p => p.Key, p => p.Value);
But I actually kind of like using foreach for this.
var result = new Dictionary<int, bool>();
foreach (var dic in items.SelectMany(d => d.Dic))
result[dic.Key] = dic.Value;