How to search for part of a dictionary key (.net vb visual studio 2008)

Could someone please tell me, how I can search for only a part of a key in a dictionary (in VB.NET)?

I use the following sample code:

    Dim PriceList As New Dictionary(Of String, Double)

    PriceList.Add("Spaghetti alla carbonara", 21.65)
    PriceList.Add("Spaghetti aglio e olio", 22.65)
    PriceList.Add("Spaghetti alla napoletana", 23.65)
    PriceList.Add("Spaghetti alla puttanesca ", 24.65)
    PriceList.Add("Spaghetti alla gricia ", 25.65)
    PriceList.Add("Spaghetti alle vongole", 26.65)
    PriceList.Add("Spaghetti Bolognese", 27.65)

    If PriceList.ContainsKey("spaghetti bolognese") Then
        Dim price As Double = PriceList.Item("spaghetti bolognese")
        Console.WriteLine("Found, price: " & price)
    End If

    If Not PriceList.ContainsKey("Bolognese") Then
        Console.WriteLine("How can I search for only a part of a key?")
    End If


If I only know a part of the key like "Bolognese" or just a part of word like "Bolo", how can I search for this part in the complete key?
BASit BulbuliaAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Wayne Taylor (webtubbs)Commented:
You'll find the answer in the question you asked at that other site.
Jacques Bourgeois (James Burger)PresidentCommented:
With PriceList
                  For x = 0 To .Keys.Count - 1
                        If .Keys(x).IndexOf("gric") > -1 Then
                              MessageBox.Show("The price of " & .Keys(x) & " is " & .Values(x).ToString)
                        End If
                  Next
            End With

Simply insert your search String as a parameter to the IndexOf method.
BASit BulbuliaAuthor Commented:
@webtubbs - > The solution at the other site does not work as the Pricelist.where (generates an error) -> for those who are interested in finding a better solution or have a work around the error - please visit :-

http://stackoverflow.com/questions/17998321/how-to-search-for-a-part-of-a-dictionary-key

@James Burger -> Your method requires a loop through the whole array and it ain't efficient and defeats the purpose of the dictionary hash.
PMI ACP® Project Management

Prepare for the PMI Agile Certified Practitioner (PMI-ACP)® exam, which formally recognizes your knowledge of agile principles and your skill with agile techniques.

Jacques Bourgeois (James Burger)PresidentCommented:
A Hash is a numeric or condensed representation of a specific string in its whole. Entries in the directory are sorted by that hash, so this is why it is efficient. It is useful to search for the whole string, but otherwise worthless.

It's a bit similar as an index on a string value in a database. Search for the whole content of the field, and it zips through. But as soon as you start looking for anything that is not the beginning of the string, by the use of LIKE for instance, you defeats its purpose because the index becomes useless.
Fernando SotoRetiredCommented:
Hi compubyte-sa;

Try the code snippet below, it should give you what you need.

Dim searchTerm As String = "Bolo"
Dim price As KeyValuePair(Of String, Double) = PriceList.Where(Function(k) k.Key.Contains(searchTerm)).FirstOrDefault()

If price.Key IsNot Nothing Then 
    Console.WriteLine("Found, price: " + price.Value.ToString() )
End If

Open in new window

BASit BulbuliaAuthor Commented:
@Fernando - I have used this code before and in Visual Studio .net 2008 I get an error -> Error      1      'Where' is not a member of 'System.Collections.Generic.Dictionary(Of String, Integer)'.      

Pic enclosed !

Full code below :-

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim DealDetail As New Dictionary(Of String, Integer)
        Dim x As Integer = 0

        Dim ffile As String = "\ums\dealdetail.csv"
        Dim f As Integer = FreeFile()

        If File.Exists(ffile) Then
            FileOpen(f, ffile, OpenMode.Input)
            While EOF(f) = False
                x = x + 1
                DealDetail.Add(LineInput(f) + Str(x), x)
                '    Dim items() As String = Split(tzz, ";")
            End While
            FileClose(f)
        End If

        Dim PriceList As New Dictionary(Of String, Integer)
        x = 0
        ffile = "\ums\pricelist.csv"
        f = FreeFile()
        If File.Exists(ffile) Then
            FileOpen(f, ffile, OpenMode.Input)
            While EOF(f) = False
                x = x + 1
                PriceList.Add(LineInput(f) + Str(x), x)
                '    Dim items() As String = Split(tzz, ";")
            End While
            FileClose(f)
        End If

        Dim Product As New Dictionary(Of String, Integer)
        x = 0
        ffile = "\ums\product.csv"
        f = FreeFile()
        If File.Exists(ffile) Then
            FileOpen(f, ffile, OpenMode.Input)
            While EOF(f) = False
                x = x + 1
                Product.Add(LineInput(f) + Str(x), x)
                '    Dim items() As String = Split(tzz, ";")
            End While
            FileClose(f)
        End If

        Dim Suppliers As New Dictionary(Of String, Integer)
        ffile = "\ums\suppliers.csv"
        f = FreeFile()
        If File.Exists(ffile) Then
            FileOpen(f, ffile, OpenMode.Input)
            While EOF(f) = False
                x = x + 1
                Suppliers.Add(LineInput(f) + Str(x), x)
                '    Dim items() As String = Split(tzz, ";")
            End While
            FileClose(f)
        End If

        x = 0
        Dim y As Integer
        Dim Z As Integer
        Dim ZZ As Integer


        Dim DiscountValue As Single
        Dim DiscountPercentage As Single
        Dim PriceN As Single
        Dim Sup As String

        Dim FoundItem As Boolean = False


        Dim pair As KeyValuePair(Of String, Integer)

        For Each pair In DealDetail

            Sup = "Unknown"
            FoundItem = False

            Label1.Text = Str(pair.Value) + " of" + Str(DealDetail.Count)

            Application.DoEvents()

            Dim items() As String = Split(pair.Key, ";")

            StartDate.Add(items(4))
            EndDate.Add(items(5))
            DiscountValue = Val(items(11))
            DiscountPercentage = Val(items(12))

            Dim searchTerm As String = "Bolo"
            Dim price As KeyValuePair(Of String, Single) = Product.Where(Function(k) k.Key.Contains(searchTerm)).FirstOrDefault()

            If price.Key IsNot Nothing Then
                Console.WriteLine("Found, price: " + price.Value.ToString())
            End If



            If Product.ContainsKey(items(3)) Then
                MsgBox("Found ! ! ! ")
            End If


        Next

Open in new window

error.where.jpg
Jacques Bourgeois (James Burger)PresidentCommented:
Where appeared in framework 3.5. If you are targeting an older version, it's not there.

Anyway, what do you think Where does in the background?

If you know about hashtables, you know that it needs to loop through the items until it finds one whose key contains the substring you are looking for. There is no way to use the optimisation of the hash in any kind of hashtable unless you look for the whole key.
it_saigeDeveloperCommented:
Let's look at what has been recommended here:
Module Module1
	Private ReadOnly watch As New Stopwatch()
	Private ReadOnly PriceList As New Dictionary(Of String, Double)() From {{"Spaghetti alla carbonara", 21.65}, {"Spaghetti aglio e olio", 22.65}, {"Spaghetti alla napoletana", 23.65}, {"Spaghetti alla puttanesca ", 24.65}, {"Spaghetti alla gricia ", 25.65}, {"Spaghetti alle vongole", 26.65}, {"Spaghetti Bolognese", 27.65}}

	Sub Main()
		Console.WriteLine("Let's do some calculations:")
		DictionaryWhere()
		KeyWhere()
		StandardFor()
		Console.ReadLine()
	End Sub

	Sub DictionaryWhere()
		Console.WriteLine()
		Console.WriteLine("Using a dictionary based where clause")
		watch.Reset()
		watch.Start()
		Dim result As KeyValuePair(Of String, Double) = PriceList.Where(Function(k) k.Key.Contains("Bologne")).FirstOrDefault()
		watch.Stop()

		If Not String.IsNullOrEmpty(result.Key) Then
			Console.WriteLine("Found: {0} for {1}", result.Key, result.Value)
		Else
			Console.WriteLine("Could not find search item")
		End If
		Console.WriteLine("Using a dictionary based where clause took {0} ms", watch.ElapsedMilliseconds)
	End Sub

	Sub KeyWhere()
		Console.WriteLine()
		Console.WriteLine("Using a key based where clause")
		watch.Reset()
		watch.Start()
		Dim result As KeyValuePair(Of String, Double) = (From item In PriceList Where item.Key.Contains("Bologne") Select item).FirstOrDefault()
		watch.Stop()

		If Not String.IsNullOrEmpty(result.Key) Then
			Console.WriteLine("Found: {0} for {1}", result.Key, result.Value)
		Else
			Console.WriteLine("Could not find search item")
		End If
		Console.WriteLine("Using a key based where clause took {0} ms", watch.ElapsedMilliseconds)
	End Sub

	Sub StandardFor()
		Console.WriteLine()
		Console.WriteLine("Using a standard forloop")
		watch.Reset()
		watch.Start()
		Dim result As New KeyValuePair(Of String, Double)
		With PriceList
			For i As Integer = 0 To .Keys.Count - 1
				If .Keys(i).IndexOf("Bologne") > -1 Then
					result = .ElementAt(i)
					Exit For
				End If
			Next
		End With
		watch.Stop()

		If Not String.IsNullOrEmpty(result.Key) Then
			Console.WriteLine("Found: {0} for {1}", result.Key, result.Value)
		Else
			Console.WriteLine("Could not find search item")
		End If
		Console.WriteLine("Using a standard forloop took {0} ms", watch.ElapsedMilliseconds)
	End Sub
End Module

Open in new window

Which produces the following output (results will vary) -Capture.JPGAs you can see here, the for loop (which is really what linq does when you come down to it), performs this search a millisecond faster than the key based search.  The key based search is, essentially, an expanded expression based statement that does the same lookup as using the Method based dictionary.Where lookup.

Draw your own conclusions but James still has the better method.

-saige-
BASit BulbuliaAuthor Commented:
@saige - thank you for response - it does show that James method is the fastest !
ArkCommented:
it does show that James method is the fastest
It does show that net framework cash queries. Try
    Sub Main()
        Console.WriteLine("Let's do some calculations:")
        StandardFor()
        KeyWhere()
        DictionaryWhere()
        Console.ReadLine()
    End Sub

Open in new window

ArkCommented:
A slightly changed code
Module Module1
    Private ReadOnly watch As New Stopwatch()
    Private ReadOnly PriceList As New Dictionary(Of String, Double)() From {{"Spaghetti alla carbonara", 21.65}, {"Spaghetti aglio e olio", 22.65}, {"Spaghetti alla napoletana", 23.65}, {"Spaghetti alla puttanesca ", 24.65}, {"Spaghetti alla gricia ", 25.65}, {"Spaghetti alle vongole", 26.65}, {"Spaghetti Bolognese", 27.65}}
    Private result As KeyValuePair(Of String, Double)
    Private passes As Integer = 100000

    Sub Main()
        Console.WriteLine("Let's do some calculations:")
        KeyWhere()
        DictionaryWhere()
        StandardFor()
        Console.ReadLine()
    End Sub

    Sub DictionaryWhere()
        result = New KeyValuePair(Of String, Double)
        watch.Reset()
        watch.Start()
        For i = 1 To passes
            result = PriceList.Where(Function(k) k.Key.Contains("Bologne")).FirstOrDefault()
        Next
        watch.Stop()
        Console.WriteLine("Using a dictionary based where clause took {0} ms", watch.ElapsedMilliseconds)
    End Sub

    Sub KeyWhere()
        result = New KeyValuePair(Of String, Double)
        watch.Reset()
        watch.Start()
        For i = 1 To passes
            Dim key = (From x In PriceList.Keys Where x.Contains("Bologne")).FirstOrDefault
            result = New KeyValuePair(Of String, Double)(key, PriceList(key))
        Next
        Console.WriteLine("Using a key based where clause took {0} ms", watch.ElapsedMilliseconds)
    End Sub

    Sub StandardFor()
        result = New KeyValuePair(Of String, Double)
        watch.Reset()
        watch.Start()
        For j = 1 To passes
            With PriceList
                For i As Integer = 0 To .Keys.Count - 1
                    If .Keys(i).IndexOf("Bologne") > -1 Then
                        result = .ElementAt(i)
                        Exit For
                    End If
                Next
            End With
        Next
        watch.Stop()
        Console.WriteLine("Using a standard forloop took {0} ms", watch.ElapsedMilliseconds)
    End Sub
End Module

Open in new window

results.PNG
BASit BulbuliaAuthor Commented:
@Ark Ummmm very interesting  ! !
ArkCommented:
Note that standard for loop is so slow in my example due to using IndexOf instead of Contains. IndexOf use StringComparison.CurrentCulture by default while Contains call IndexOf with StringComparison.Ordinal. If change IndexOf in for..next loop to Contains (or change default call with overloaded using StringComparison.Ordinal), this method will be 20-25% faster, though remain slowest among all 3.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
BASit BulbuliaAuthor Commented:
Thanks guys  ! !
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.