A C# converting a query to dictionary:
public class myClass
{
public int my_id;
public Dictionary<string, Dictionary<string, string[]>> myDict;
}
Dictionary<string, myClass> dataDict;
Dictionary<int, Dictionary<string, myClass>> query = (from happen in dataDict
group happen by happen.Value.my_id into g
select g).ToDictionary( ?? );
I do not know what I should put in ( ?? ).
Any help would be appreciated.
Try this:
var query = (from happen in dataDict
group happen by happen.Value.my_id into g select g)
.ToDictionary(g => g.Key, g => g.ToDictionary(x => x.Key, x => x.Value));
Related
I seem to have a hard time figuring out an easy way of inserting my old and new registration into a dictionary formatted like
Dictionary<int, List<Registration>, List<Registration>>
Where the first list contain oldReg, and the other one contains new registration.
They have an id in commmon, which has to be the key, and if that is not the case, then the shall the other list be empty.
I seem to have a hard time figuring out an Linq statement capable of doing so, I would assume this was a job for GroupBy or GroupJoin, but cannot figure out how it should look like..
MVC: https://dotnetfiddle.net/BIbPqY
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
Dictionary<string, object> openWith =
new Dictionary<string, object>();
openWith.Add("txt", "notepad.exe");
openWith.Add("bmp", "paint.exe");
openWith.Add("dib", "paint.exe");
openWith.Add("rtf", "wordpad.exe");
Registration reg1 = new Registration()
{
id = 1,
attributes = openWith
};
Registration reg2 = new Registration()
{
id = 2,
attributes = openWith
};
Registration reg3 = new Registration()
{
id = 1,
attributes = openWith
};
Registration reg4 = new Registration()
{
id = 2,
attributes = openWith
};
List<Registration> oldReg = new List<Registration>() {reg1, reg2 };
List<Registration> newReg = new List<Registration>() {reg3, reg4 };
Console.WriteLine("Hellow World");
}
public class Registration
{
public int id {get; set;}
public Dictionary<string, object> attributes {get; set;}
}
}
My current way of handling is by creating two dictionaries by using groupBy
Dictionary<int, List<Registration>> oldRegDic =
oldReg.GroupBy(o => o.id).ToDictionary(g => g.Key, g => g.ToList());
Dictionary<int, List<Registration>> newRegDic =
newReg.GroupBy(o => o.id).ToDictionary(g => g.Key, g => g.ToList());
Dictionary<int, (List<Registration>, List<Registration>)> oldAndNewRegistrationDictionary = new();
foreach (KeyValuePair<int, List<Registration>> newReg in newRegistrationDictionary)
{
(List<EntityRegistration>, List<EntityRegistration>) oldNewPair = new()
{
Item1 = oldRegDic[newReg.Key], Item2 = newRegDic[newReg.Key]
};
}
And then iterate through them both an add them to a new Dictionary, but thats looks very inefficient.
It is good to have Full Join here, but it can be emulated by two queries:
var query1 =
from n in newReg
join o in oldReg on n.id equals o.id into gj
from o in gj.DefaultIfEmpty()
select new { id = n.id, n, o };
var query2 =
from o in oldReg
join n in newReg on o.id equals n.id into gj
from n in gj.DefaultIfEmpty()
where n == null
select new { id = o.id, n, o };
var result = query1.Concat(query2)
.ToDictionary(x => x.id, x => Tuple.Create(x.o, x.n));
I am trying to converting a Tuple<List<Guid>, string> to Dictionary<Guid, List<string>>. This is what I have so far:
var listOfTuples = GetListOfTuples(); // returns type List<Tuple<List<Guid>, string>>
var transformedDictionary = new Dictionary<Guid, List<string>>();
foreach (var listOfTuple in listOfTuples)
{
foreach (var key in listOfTuple.Item1)
{
if (!transformedDictionary.ContainsKey(key))
transformedDictionary[key] = new List<string> { listOfTuple.Item2 };
else transformedDictionary[key].Add(listOfTuple.Item2);
}
}
Is there a better way of doing this, perhaps using LINQ; SelectMany, Grouping, or toDictionary?
Update: I have tried this, but clearly not working:
listOfTuples.ToList()
.SelectMany(x => x.Item1,(y, z) => new { key = y.Item2, value = z })
.GroupBy(p => p.key)
.ToDictionary(x => x.Key, x => x.Select(m => m.key));
You are close. The problem is with selecting the right key and value
var result = listOfTuples.SelectMany(t => t.Item1.Select(g => (g, str: t.Item2)))
.GroupBy(item => item.g, item => item.str)
.ToDictionary(g => g.Key, g => g.ToList());
The mistake is here (y, z) => new { key = y.Item2, value = z } - you want the key to be the Guid and therefore instead of it being Item2 it should be z which is the Guid. So you can go with the way I wrote it or just
(y, z) => new { key = z, value = y.Item2 }
Also the .ToList() at the beginning is not needed. You say that listOfTuples already returns a list
I have a dictionary for which I want to retrieve results matching to those of list
here is what I have done so far
Dictionary<string, Dictionary<string, int>> SomeDictionary = new Dictionary<string, Dictionary<string, int>>();
List<int> MyList = new List<int>()
{
2,3,4,5
};
Dictionary<string, int> internalDictionary = new Dictionary<string, int>();
internalDictionary.Add("two", 2);
internalDictionary.Add("three", 3);
internalDictionary.Add("four", 4);
internalDictionary.Add("five", 5);
Dictionary<string, int> AnotherDictionary = new Dictionary<string, int>();
AnotherDictionary.Add("six", 6);
AnotherDictionary.Add("three", 3);
AnotherDictionary.Add("seven", 7);
SomeDictionary.Add("Dictionary1", internalDictionary);
SomeDictionary.Add("Dictionary2", AnotherDictionary);
var res = from l in MyList
select(from q in
(from p in
(from s in SomeDictionary
select s)
select p) where q.Value.Equals(l) select q);
The value returned is null. what am i Missing ?
I need matching KeyValuePair where value matches internal dictionary values.
Explanation:
Select Many to combine all internal dictionaries into All In One dictionary.
List and SelectMany are IEnumerable. So join is possible between to IEnumerable objects.
However, List contains string value while IEnumerable object returned from SelectMany has integer value.
So created inner join query with string and integer value after converting integer to string. Refer screencast that might be required output
Screen cast showing working code
This Linq snippet may be helpful:
var allinone = (from l in MyList
join d in SomeDictionary.SelectMany(s => s.Value) on l equals d.Value
select d);
Try this:
var res = from l in MyList
from q in SomeDictionary
from w in q.Value
where w.Value == l
select w;
I get this:
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;