Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Alternative to Case

Posted on 2006-06-22
12
Medium Priority
?
292 Views
Last Modified: 2008-03-17
I am using a case statement to take an input string and return a call to a function.

Example:
Select Case sSwitch
   Case "ABC"
      Return FunctionABC
   Case "XYZ"
      Return FunctionXYZ
...
End Select

The problem that i have is that there are several hundred cases, and it is in a loop, so it is taking a real long time..  Is there a VB.Net statement or construct that can search through a list of cases and return a function pointer? Or some other method that would be faster?

Thanks!
0
Comment
Question by:a1x
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 2
  • 2
  • +2
12 Comments
 
LVL 18

Expert Comment

by:JR2003
ID: 16964805
You could nest case statement and test the first character.

Select Case Left(sSwitch, 1)
   Case "A"
        Select Case sSwitch
           Case "ABC"
              Return FunctionABC
           Case "ABD"
              Return FunctionABD
        End Select
   Case "B"
        Select Case sSwitch
           Case "BCD"
              Return FunctionBCD
           Case "BDS"
              Return FunctionBDS
        End Select
   Case "C"
        Select Case sSwitch
           Case "CDE"
              Return FunctionCDE
           Case "CDF"
              Return FunctionCDF
        End Select
...
End Select

That way you reduce the average number test for each item.
0
 
LVL 64

Accepted Solution

by:
Fernando Soto earned 1660 total points
ID: 16965370
Hi a1x;

Here is a way to do it without a Case statements.

    ' Declear pointer to a function using Delegate
    Delegate Function delFunction() As String

    ' Hash table to hold key / value pair
    Dim ht As New Hashtable

    Private Sub Form1_Load(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load

        ' Load Hash table with the key and pointer to function to call
        Dim func As delFunction
        func = AddressOf FunctionABC
        ht.Add("ABC", func)
        func = AddressOf FunctionDEF
        ht.Add("DEF", func)

    End Sub

Then you can call them this way which is much faster then going through 100 case test.

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

        Dim deleg As delFunction
        deleg = CType(ht("ABC"), delFunction)
        Console.WriteLine(deleg())
        deleg = CType(ht("DEF"), delFunction)
        Console.WriteLine(deleg())

    End Sub

    Private Function FunctionABC() As String
        Return "ABC"
    End Function

    Private Function FunctionDEF() As String
        Return "DEF"
    End Function

Fernando
0
 
LVL 34

Expert Comment

by:Sancler
ID: 16967598
I doubt very much that it is your use of SELECT CASE that is causing your program to take "a real long time".  Try this

    Private Sub MakeCode(ByVal FileName As String)
        Dim sr As New StreamWriter(FileName)
        sr.WriteLine("Dim ticks As Long = Now.Ticks")
        sr.WriteLine("for a as integer = 1 to 1000")
        sr.WriteLine("dim b as string = cstr(a)")
        sr.WriteLine("select case a")
        For i As Integer = 1 To 1000
            Dim s As String = "Case " & Chr(34) & i.ToString & Chr(34)
            sr.WriteLine(s)
            s = "debug.writeline(" & Chr(34) & i.ToString & Chr(34) & ")"
            sr.WriteLine(s)
        Next
        sr.WriteLine("end select")
        sr.WriteLine("next")
        sr.WriteLine("Dim timelapse As Long = (Now.Ticks - ticks) / TimeSpan.TicksPerSecond")
        sr.WriteLine("MsgBox(timelapse)")
        sr.Close()
    End Sub

All it does is produce the code for a 1000 select case statement and code to loop through it looking for each value.  Although the values are derived from numbers they are expressed as strings to make it similar to your situation.

If you run that and then select all, copy and paste the text from the file it produces into a sub and run that sub I doubt that you will find it "taking a real long time".  Different systems will produce different results but, on mine, the result in the message box at the end was 2 seconds.

So my guess is that, if you want to reduce the time, you should be looking at the functions which your SELECT CASE routine is directing program flow to rather than at the SELECT CASE statement itself.

Roger
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 34

Expert Comment

by:Sancler
ID: 16968598
It just occurred to me that, although I had added the line

        sr.WriteLine("dim b as string = cstr(a)")

so as to produce a "text" select case rather than a "number" select case, to line up with yours, I did not change

        sr.WriteLine("select case a")

to

        sr.WriteLine("select case b")

I've now done that and re-run.  The time on my system is now down to 1 second ;-)

Roger
0
 
LVL 5

Author Comment

by:a1x
ID: 16971679
Thanks FernandoSoto!

Exactly what I was looking for.  Tremendous increase in speed.
0
 
LVL 64

Expert Comment

by:Fernando Soto
ID: 16972143
No problem glad I was able to help.
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 16972236
You must have one LOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG Form1_Load() sub eh?....   =)
0
 
LVL 34

Expert Comment

by:Sancler
ID: 16972288
"Tremendous increase in speed".  That's interesting.  I've just run comparative tests, using a similar approach to that outlined above.  That is, I wrote code to create 1000 instances of delegate functions and fill a hashtable with their addresses.  I then copied that code into a form and iterated through a 1000 loop to call each function once.  Here's the results.

Select case: 875 milliseconds
Select case: 594 milliseconds
Select case: 609 milliseconds
Select case: 578 milliseconds
Select case: 609 milliseconds
Select case: 797 milliseconds

Delegate: 1312 milliseconds
Delegate: 703 milliseconds
Delegate: 719 milliseconds
Delegate: 750 milliseconds
Delegate: 703 milliseconds
Delegate: 734 milliseconds

I must stress that I'm not arguing with Fernando's answer, or the award of points to him.  What matters is what works.

But I can't help wondering why.  It's just that, so far as I know, a SELECT CASE statement in fact works with, in the background, its own hashtable so I would have been surprised if, of itself, the upfront hashtable approach was any quicker.  My tests show that it isn't.  For all practical purposes it is the same.  So why, in the setting in this question, has it produced a "tremendous increase in speed"?

Any thoughts, anyone?

Roger
0
 
LVL 34

Expert Comment

by:Sancler
ID: 16972304
Mike

Yes it is.  My intermediate code file was 118KB ;-)

Roger

0
 
LVL 5

Author Comment

by:a1x
ID: 16972531
Perhaps you are on Framework 2.0?  I am on 1.1.

Do you have the code to create the hash table functions?.  I'm curious.
0
 
LVL 34

Expert Comment

by:Sancler
ID: 16972954
I did it in VB.NET 2003, Framework 1.1

Here's the code

    Private Sub MakeCode2(ByVal FileName As String)
        Dim sr As New StreamWriter(FileName)
        ' Declear pointer to a function using Delegate
        sr.WriteLine("Delegate Function delFunction() As String")

        ' Hash table to hold key / value pair
        sr.WriteLine("Dim ht As New Hashtable")

        sr.WriteLine("Private Sub Form1_Load(ByVal sender As Object,ByVal e As System.EventArgs) Handles MyBase.Load")

        ' Load Hash table with the key and pointer to function to call
        sr.WriteLine("Dim func As delFunction")
        For i As Integer = 1 To 1000
            sr.WriteLine("func = AddressOf Function" & i.ToString)
            sr.WriteLine("ht.Add(" & Chr(34) & i.ToString & Chr(34) & ", func)")
        Next
        sr.WriteLine("End Sub")
        For i As Integer = 1 To 1000
            sr.WriteLine("Private Function Function" & i.tostring & "() As String")
            sr.WriteLine("Return " & Chr(34) & i.ToString & Chr(34))
            sr.WriteLine("End Function")
        Next
        sr.Close()
        MsgBox("done")

    End Sub

The routine that I wrapped the iteration in, having used the above to generate the code which I copied into the form, was

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        Dim ticks As Long = Now.Ticks
        Dim deleg As delFunction
        For a As Integer = 1 To 1000
            deleg = CType(ht(a.ToString), delFunction)
            Debug.WriteLine(deleg())
        Next
        Dim timelapse As Long = (Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond
        MsgBox(timelapse)
        Debug.WriteLine("Delegate: " & timelapse & " milliseconds")
    End Sub

The "Select Case" test just used the code from my earlier post, with the final output changed to debug and put in milliseconds.

Have fun with it.

Roger
0
 
LVL 34

Expert Comment

by:Sancler
ID: 16973011
I've just converted the project to VB.NET 2005, Framework 2 and re-run the tests.  Here's the results for those.

Select case: 1484 milliseconds
Select case: 1266 milliseconds
Select case: 1359 milliseconds
Select case: 1297 milliseconds
Select case: 1266 milliseconds
Select case: 1297 milliseconds

Delegate: 1734 milliseconds
Delegate: 1266 milliseconds
Delegate: 1219 milliseconds
Delegate: 1188 milliseconds
Delegate: 1172 milliseconds
Delegate: 1172 milliseconds

In relative terms the two methods are still, for all practical purposes, the same - although the slight edge that Select Case had before Delegate has now.  But the most interesting thing is that the 2003 version is quite a bit faster than the 2005 version.  There's progress for you!

Roger
0

Featured Post

Enroll in October's Free Course of the Month

Do you work with and analyze data? Enroll in October's Course of the Month for 7+ hours of SQL training, allowing you to quickly and efficiently store or retrieve data. It's free for Premium Members, Team Accounts, and Qualified Experts!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: Kraeven
Introduction Remote Share is a simple remote sharing tool, enabling you to see, add and remove remote or local shares. The application is written in VB.NET targeting the .NET framework 2.0. The source code and the compiled programs have been in…
Parsing a CSV file is a task that we are confronted with regularly, and although there are a vast number of means to do this, as a newbie, the field can be confusing and the tools can seem complex. A simple solution to parsing a customized CSV fi…
Video by: ITPro.TV
In this episode Don builds upon the troubleshooting techniques by demonstrating how to properly monitor a vSphere deployment to detect problems before they occur. He begins the show using tools found within the vSphere suite as ends the show demonst…
In response to a need for security and privacy, and to continue fostering an environment members can turn to for support, solutions, and education, Experts Exchange has created anonymous question capabilities. This new feature is available to our Pr…
Suggested Courses

610 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question