Reputation: 36816
I have used the "select" keyword and extension method to return an IEnumerable<T>
with LINQ, but I have a need to return a generic Dictionary<T1, T2>
and can't figure it out. The example I learned this from used something in a form similar to the following:
IEnumerable<T> coll = from x in y
select new SomeClass{ prop1 = value1, prop2 = value2 };
I've also done the same thing with extension methods. I assumed that since the items in a Dictionary<T1, T2>
can be iterated as KeyValuePair<T1, T2>
that I could just replace "SomeClass" in the above example with "new KeyValuePair<T1, T2> { ...
", but that didn't work (Key and Value were marked as readonly, so I could not compile this code).
Is this possible, or do I need to do this in multiple steps?
Thanks.
Upvotes: 208
Views: 200093
Reputation: 82345
The extensions methods also provide a ToDictionary extension. It is fairly simple to use, the general usage is passing a lambda selector for the key and getting the object as the value, but you can pass a lambda selector for both key and value.
class SomeObject
{
public int ID { get; set; }
public string Name { get; set; }
}
SomeObject[] objects = new SomeObject[]
{
new SomeObject { ID = 1, Name = "Hello" },
new SomeObject { ID = 2, Name = "World" }
};
Dictionary<int, string> objectDictionary =
objects.ToDictionary(
o => o.ID,
o => o.Name);
Then objectDictionary[1]
Would contain the value "Hello"
Upvotes: 363
Reputation: 131
I modified the solution of hross because his version puts alle items of an array into one dictionary element.
I wanted to have each array item in its own dictionary item. This has two advantages:
The key to this solution is the fact that JToken knows its path (JToken.Path) so it is not necessary to assemble it for yourself. This makes the new solution surprisingly simple.
public static Dictionary<string, string?>? GetJsonDictionary(JToken? token)
{
if (token == null)
{
return null;
}
var dict = new Dictionary<string, string?>();
ParseJToken(token, dict);
return dict;
}
private static void ParseJToken(JToken token, Dictionary<string, string?> nodes)
{
if (token.HasValues)
{
// The node has children.
foreach (JToken child in token.Children())
{
ParseJToken(child, nodes);
}
}
else
{
// The node is a leaf.
nodes.Add(token.Path, token.ToString());
}
}
Upvotes: 0
Reputation: 9924
A more explicit option is to project collection to an IEnumerable of KeyValuePair
and then convert it to a Dictionary.
Dictionary<int, string> dictionary = objects
.Select(x=> new KeyValuePair<int, string>(x.Id, x.Name))
.ToDictionary(x=>x.Key, x=>x.Value);
Upvotes: 75
Reputation: 27118
var dictionary = (from x in y
select new SomeClass
{
prop1 = value1,
prop2 = value2
}
).ToDictionary(item => item.prop1);
That's assuming that SomeClass.prop1
is the desired Key
for the dictionary.
Upvotes: 46