Reputation: 64207
public class Person
{
public string NickName{ get; set; }
public string Name{ get; set; }
}
var pl = new List<Person>;
var q = from p in pl
where p.Name.First() == 'A'
orderby p.NickName
select new KeyValuePair<String, String>(p.NickName, p.Name);
var d1 = q.ToList(); // Gives List<KeyValuePair<string, string>>
var d2 = q.ToDictionary(); // Does not compile
How to get Dictionary<string, string>?
Upvotes: 42
Views: 3624
Reputation: 35696
EDIT
If you really feel you need to get from IEnumerable<KeyValuePair<TKey, TValue>>
to a Dictionary
implicitly you could add this extension.
public static IDictionary<TKey, ToValue> ToDictionary<TKey, TValue>(
this IEnumerable<KeyValuePair<TKey, TValue>> source)
{
return source.ToDictionary(p => p.Key, p => p.Value);
}
Then you could call ToDictionary()
on any IEnumerable<KeyValuePair<TKey, TValue>>
.
EDIT 2
If you are anticipating duplicates then you could create a ToLookup()
extension too.
public static ILookup<TKey, TValue> ToLookup<TKey, TValue>(
this IEnumerable<KeyValuePair<TKey, TValue>> source)
{
return source.ToLookup(p => p.Key, p => p.Value);
}
Alternatively, if you really want to discard results, you could add an overload for ToDictionary
.
public static IDictionary<TKey, ToValue> ToDictionary<TKey, TValue>(
this IEnumerable<KeyValuePair<TKey, TValue>> source,
Func<<IEnumerable<TValue>, TValue> selector)
{
return source
.Lookup(p => p.Key, p => p.Value);
.ToDictionary(l => l.Key, l => selector(l));
}
If you arbitrarily discard all but the "first" (what does that mean without an OrderBy
) item, you could use this extension like this,
pairs.ToDictionary(v => v.First());
Overall, you can remove most of your code and do,
var q = from p in pl
where p.Name.First() == 'A'
select p;
var d = q.ToDictionary(p => p.NickName, p => p.Name);
If there could be duplicates, do
var d = q.ToLookup(p => p.NickName, p => p.Name);
but note, this returns an ILookup<TKey, TElement>
, the Item
indexer of which, returns an IEnumerable<TElement>
so you don't discard data.
Upvotes: 7
Reputation: 1
You can get Dictionary from LINQ query also by casting it :
var d2 = (Dictionary<string, string>)q;
This worked on Visual Studio 2013.
Upvotes: -1
Reputation: 15440
I realize that this was tagged with c#, but I was literally just trying to figure out how to do this in vb.net yesterday, so I thought I would share how you'd do this in VB as well:
Public Class Person
Property NickName As String
Property Name As String
End Class
Sub Main()
Dim p1 As New List(Of Person)
'*** Fill the list here ***
Dim q = (From p In p1
Where p.Name.First = "A"
Select p.NickName, p.Name).ToDictionary(
Function(k) k.NickName,
Function(v) v.Name)
End Sub
Upvotes: 0
Reputation: 48537
You need to specify the values for the Dictionary
var d2 = q.ToDictionary(p => p.NickName, p => p.Name);
Upvotes: 43
Reputation: 460028
A dictionary cannot contain multiple equal keys, so you should ensure (or know) that this is not the case. You could use GroupBy
to ensure it:
Dictionary<string, string> dict = pl
.Where(p => p.Name.First() == 'A')
.GroupBy(p => p.NickName)
.ToDictionary(g => g.Key, g => g.First().Name);
Upvotes: 11
Reputation: 30688
Try following for NickName as Key, and Name as Value
var d2 = q.ToDictionary (p => p.NickName, p=>p.Name);
But note that dictionary does not allow duplicate, so above will throw error for duplicate records with same nickname. Perhaps you would like to use Lookup that is similar to Dictionary, but allows duplicates
var d2 = q.ToLookup (p => p.NickName, p=>p.Name);
Upvotes: 5