Skip to content

Instantly share code, notes, and snippets.

@digiguru
Created February 11, 2012 07:09
Show Gist options
  • Save digiguru/1797400 to your computer and use it in GitHub Desktop.
Save digiguru/1797400 to your computer and use it in GitHub Desktop.
To convert any list into a complicated nest of dictionaries for ultra fast lookup.
<ExtensionAttribute()>
Public Function ToMultiKeyDictionary(Of TSource, TSecKey)(ByVal source As IEnumerable(Of TSource), ByVal ParamArray func() As Func(Of TSource, TSecKey)) As IDictionary
'EXAMPLE USAGE
'dict = students.ToMultiKeyDictionary(
' {
' Function(x) x.Age,
' Function(x) x.Location,
' Function(x) x.Job,
' Function(x) x.Name,
' Function(x) x})
Dim reverseCollection As New Dictionary(Of Integer, Type)
Dim functionsCount As Integer = func.Count
Dim dictTypeCollection As New List(Of IDictionary)
Dim instanceOfCurrentDictionaryArgument As New Object
Dim dictionaryArgQueue As Object = Nothing
Dim dictionaryTypes As New List(Of Type)
For i = 0 To functionsCount - 1
reverseCollection.Add(i, source.Select(func(func.Count() - (i + 1))).FirstOrDefault().GetType())
Next
Dim typeOfGenericDictionary As Type
Dim dictionaryTypeArgs() As Type
Dim newConstructedType As Type
Dim currentDictionaryInstance As IDictionary
For i = 0 To reverseCollection.Count - 1
If reverseCollection(i) IsNot GetType(String) Then
instanceOfCurrentDictionaryArgument = Activator.CreateInstance(reverseCollection(i))
Else
instanceOfCurrentDictionaryArgument = String.Empty
End If
If instanceOfCurrentDictionaryArgument IsNot Nothing AndAlso dictionaryArgQueue IsNot Nothing Then
typeOfGenericDictionary = GetType(Dictionary(Of ,))
dictionaryTypeArgs = {instanceOfCurrentDictionaryArgument.GetType(), dictionaryArgQueue.GetType()}
newConstructedType = typeOfGenericDictionary.MakeGenericType(dictionaryTypeArgs)
currentDictionaryInstance = Activator.CreateInstance(newConstructedType)
dictionaryTypes.Add(newConstructedType)
dictionaryArgQueue = currentDictionaryInstance
Else
dictionaryArgQueue = instanceOfCurrentDictionaryArgument
End If
Next
Dim dict As IDictionary = Activator.CreateInstance(dictionaryTypes.Last())
'If dict IsNot Nothing Then
Dim queueObj As Object
For Each item In source
Dim currentItem = item
Dim newObject1 = Activator.CreateInstance(dict.GetType)
Dim iterDict As IDictionary = dict
Dim itemAddedFlag As Boolean = False
Dim currentItemInCollection As IEnumerable(Of TSource)
For i = 0 To func.Count - 1
currentItemInCollection = source.Where(Function(x) x.Equals(currentItem))
Dim currentKey As TSecKey = currentItemInCollection.Select(func(i)).FirstOrDefault()
If iterDict.Contains(currentKey) AndAlso iterDict(currentKey) IsNot Nothing Then
iterDict = iterDict(currentKey)
Else
queueObj = Nothing
For k = 0 To reverseCollection.Count - 1
If queueObj Is Nothing Then
queueObj = currentItemInCollection.Select(func(functionsCount - (k + 1))).FirstOrDefault()
Else
Dim curObject As Object = currentItemInCollection.Select(func(functionsCount - (k + 1))).FirstOrDefault()
Dim currentDictionaryFromReverse As IDictionary = Activator.CreateInstance(dictionaryTypes(k - 1))
If iterDict.GetType() = currentDictionaryFromReverse.GetType() Then
iterDict.Add(curObject, queueObj)
itemAddedFlag = True
Exit For
End If
currentDictionaryFromReverse.Add(curObject, queueObj)
queueObj = currentDictionaryFromReverse
End If
Next
If itemAddedFlag Then
Exit For
End If
End If
Next
Next
Return dict
End Function
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment