问题
There are many, many threads on ways to get the "first" item from a Dictionary
, and various answers as to why such a thing is not really a good idea because there's no internal ordering. But mine's a SortedDictionary
, so those arguments don't apply. Yet I cannot find a way to get the Nth item from a SortedDictionary
any easier than a Dictionary
.
Here is my SD:
FRs As SortedDictionary(Of DateTime, ScheduleItem)
I see a few hints that I should be able to do:
If FRs.Count = 1 Then
FirstFR = FRs.Keys(0)
But that is not valid in my code - it says it has no defaults and cannot be indexed. .First
and other options appear to all be in LINQ, which I cannot target. So is there any simple way to access it in this fashion?
Note: any solution offered must not use LINQ, which does not exist on many non-Wintel platforms.
回答1:
The problem is that a SortedDictionary
is indeed ordered by the key. But that does not mean that you can access it via index. So if you can't use LINQ:
Dim firstFR As KeyValuePair(Of DateTime, ScheduleItem)
For Each kv In FRs
firstFR = kv
Exit For
Next
Otherwise you could simply use First
/ FirstOrDefault
.
Sidenote: since a KeyValuePair(Of Tkey, TValue)
is a structure, therefore a value type, it is never null
/Nothing
. You could check for an empty dictionary in this ugly way:
If firstFR.Equals(New KeyValuePair(Of DateTime, ScheduleItem))
Console.WriteLine("Empty dictionary")
End If
So it's much more readable to use If FRs.Count = 0 Then ...
.
Update: if you just want the key or value at a given index you can use:
Dim firstSchedule As Date = FRs.Keys(0)
or the first Date
in it:
Dim firstDate As ScheduleItem = FRs.Values(0)
On this way you could actually get both via index even without LINQ:
Dim firstFR = new KeyValuePair(Of DateTime, ScheduleItem)(FRs.Keys(0), FRs.Values(0))
Disclaimer: according to my question here this works only if you have imported System.Linq
, then Enumerable.ElementAt
is used implicitly which enumerates a sequence to find an item via index if the type doesn't implement IList(Of T)
. So don't use it in this case.
回答2:
Linq is mostly just a series of extension methods, so you can write own:
Imports System
Imports System.Collections.Generic
Imports System.Runtime.CompilerServices
Public Module EnumerableExtensions
<Extension()>
Public Function FirstValue(Of TKey, TValue)(source As SortedDictionary(Of TKey, TValue)) As TValue
For Each kvp In source
Return kvp.Value
Next
Return Nothing
End Function
End Module
Public Module Module1
Public Sub Main()
Dim a As SortedDictionary(Of string, string) = new SortedDictionary(Of string, string)
a.Add("foo", "1 - foo")
a.Add("bar", "2 - bar")
Console.WriteLine(a.FirstValue())
End Sub
End Module
Here's the example running in dotnetfiddle.
来源:https://stackoverflow.com/questions/36918321/first-item-in-a-sorteddictionary