|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
a vb.net equivalent to the sql IN function?I need to get a set of comma delimited client ids from a config file to test
against while running through my main processing loop. If a given clientid matches any of the ids in the list, I don't want to send email to them. What is the best way to code that? I was thinking of the idea of if currentClientID is not in the list of these clientids, then ..... Thanks, Greg Hello hazz,
While not incredibly sexy, an easy way to do this would be: Dim tIDStr As String = "1,2,3,4,5,6,7,8,9" Dim tIDs() As String = tIDStr.Split(",") If (tIDs.GetLowerBound(0) - 1) = Array.IndexOf(tIDs, "3") Then ' NOT IN ARRAY Else ' IN ARRAY End If There are of course other methods. Enjoy, -Boo Show quoteHide quote > I need to get a set of comma delimited client ids from a config file > to test > against while running through my main processing loop. > If a given clientid matches any of the ids in the list, I don't want > to send > email to them. > What is the best way to code that? I was thinking of the idea of if > currentClientID is not in the list of these clientids, then ..... > > Thanks, > Greg GhostInAK wrote:
Show quoteHide quote > Hello hazz, You can get this down to one (ugly) line:> > While not incredibly sexy, an easy way to do this would be: > > Dim tIDStr As String = "1,2,3,4,5,6,7,8,9" > Dim tIDs() As String = tIDStr.Split(",") > > If (tIDs.GetLowerBound(0) - 1) = Array.IndexOf(tIDs, "3") Then > ' NOT IN ARRAY > Else > ' IN ARRAY > End If > > There are of course other methods. Dim theList As String = "1,2,33,56,7,8,9" Dim theItem As String = "56" Dim contains As Boolean contains = DirectCast(theList.Split(","c), IList).Contains(theItem) But this should really be hidden away in a utility class that just exposes a Contains method that takes a comma-delimited string and an item. -- Larry Lard Replies to group please Larry Lard wrote:
> GhostInAK wrote: OK, I'm [probably] going to rekindle a Religious War here but, >> Dim tIDStr As String = "1,2,3,4,5,6,7,8,9" >> Dim tIDs() As String = tIDStr.Split(",") >> If (tIDs.GetLowerBound(0) - 1) = Array.IndexOf(tIDs, "3") Then >> >> There are of course other methods. hopefully, learn something at the same time ... In VB6, I'd have done [something like] this: Dim sSearch As String = "1,2,3,4,5,6,7,8,9" Dim sTarget As String = "4" If ("," & sSearch & ",").IndexOf("," & sTarget & ",") > -1 Then . . . End If Is this horribly, horribly wrong in our Brave New World? TIA, Phill W. Phill W. wrote:
Show quoteHide quote > Larry Lard wrote: Well, it works, which is good, and it's not horribly ugly, which is> > GhostInAK wrote: > > >> Dim tIDStr As String = "1,2,3,4,5,6,7,8,9" > >> Dim tIDs() As String = tIDStr.Split(",") > >> If (tIDs.GetLowerBound(0) - 1) = Array.IndexOf(tIDs, "3") Then > >> > >> There are of course other methods. > > OK, I'm [probably] going to rekindle a Religious War here but, > hopefully, learn something at the same time ... > > In VB6, I'd have done [something like] this: > > Dim sSearch As String = "1,2,3,4,5,6,7,8,9" > Dim sTarget As String = "4" > > If ("," & sSearch & ",").IndexOf("," & sTarget & ",") > -1 Then > . . . > End If > > Is this horribly, horribly wrong in our Brave New World? better, and also you are using IndexOf rather than Instr, so you're clearly well on the way to thinking in a .NET way :) The only comment I'd make is that stylistically I'd prefer my method (cast to IList and use .Contains), because semantically it does only what is necessary (determines containment); whereas you obtain the actual _position_ of the sought item in the searched list, only to throw it away. A matter of taste, really. -- Larry Lard Replies to group please
Show quote
Hide quote
> Larry Lard wrote: As with most things, the best option when faced with a number of alternatives > >> GhostInAK wrote: >> >>> Dim tIDStr As String = "1,2,3,4,5,6,7,8,9" >>> Dim tIDs() As String = tIDStr.Split(",") >>> If (tIDs.GetLowerBound(0) - 1) = Array.IndexOf(tIDs, "3") Then >>> There are of course other methods. >>> > OK, I'm [probably] going to rekindle a Religious War here but, > hopefully, learn something at the same time ... > > In VB6, I'd have done [something like] this: > > Dim sSearch As String = "1,2,3,4,5,6,7,8,9" > Dim sTarget As String = "4" > If ("," & sSearch & ",").IndexOf("," & sTarget & ",") > -1 Then > . . . > End If > Is this horribly, horribly wrong in our Brave New World? is to test them against each other. I was expecting to recommend the .Contains method mentioned by Larry Lard, but my test rig shows that it is the slowest option. I did need to make some tweaks (most notably in GhostInAK's post which returned true only if the item was not in the search pattern). I also made some optomizations to pre evaluate items which didn't change for each iteration of the test. Essentially in each test, I am testing the values 0-10 against a list of numbers 1-9 to see if they match, if so, add them to a running total of successful matches. I am running this test 1000 times for each variant to try to get a significant result. The results are similar if I change the number of iterations to 1 or 1,000,000. Feel free to try this for yourself to see if you can come up with a better algorhythm. Naturally, there is often a trade-off between performance and maintainablility. You will need to determine which option is the best for your situation. Here is my test rig (using 2005): Public Shared Sub Main() Const IterationCount As Integer = 1000 Dim sw As New Stopwatch Dim Pattern As String = "1,2,3,4,5,6,7,8,9" Dim PatternArray() As String = Pattern.Split(",") Dim CountSuccess As Integer Console.Write("method1: ") sw.Start() For iterations As Integer = 1 To IterationCount For TestItem As Integer = 0 To 10 If Not (Array.IndexOf(PatternArray, TestItem.ToString) = -1) Then CountSuccess += 1 End If Next Next sw.Stop() Console.WriteLine(sw.ElapsedTicks.ToString) Console.Write("method2: ") sw.Start() Dim TestPattern As String = "," & Pattern & "," For iterations As Integer = 1 To IterationCount For TestItem As Integer = 0 To 10 If TestPattern.IndexOf("," & TestItem.ToString & ",") > -1 Then CountSuccess += 1 End If Next Next sw.Stop() Console.WriteLine(sw.ElapsedTicks.ToString) Console.Write("method3: ") Dim Test3PatternList As IList = Pattern.Split(","c) sw.Start() For iterations As Integer = 1 To IterationCount For TestItem As Integer = 0 To 10 If Test3PatternList.Contains(TestItem.ToString) Then CountSuccess += 1 End If Next Next sw.Stop() Console.WriteLine(sw.ElapsedTicks.ToString) Console.WriteLine("Total success: " & CountSuccess.ToString) Console.WriteLine("Total should equal: " & (9 * 3 * IterationCount).ToString) Console.ReadLine() End Sub Here are the results when run in release mode: method1: 22803 method2: 57436 method3: 88614 Total success: 27000 Total should equal: 27000 Jim Wooley http://devauthority.com/blogs/jwooley/default.aspx Jim Wooley wrote:
Show quoteHide quote >> Larry Lard wrote: Thanks for that, Jim.> Dim Pattern As String = "1,2,3,4,5,6,7,8,9" > Dim PatternArray() As String = Pattern.Split(",") > Dim CountSuccess As Integer > > Console.Write("method1: ") > If Not (Array.IndexOf(PatternArray, TestItem.ToString) = -1) Then .. . . > Console.Write("method2: ") > If TestPattern.IndexOf("," & TestItem.ToString & ",") > -1 Then .. . . > Console.Write("method3: ") > If Test3PatternList.Contains(TestItem.ToString) Then .. . . > Here are the results when run in release mode: > > method1: 22803 > method2: 57436 > method3: 88614 If nothing else, it shows that my "throw-away String" method takes more than twice as long to run as searching for an element in an array - another VB favourite on its way to the Scrap Heap, me thinks. Regards, Phill W. Hello Jimbo,
I would like to point out that Larry Lard is quite correct in his assertion that whichever method is chosen it needs to be abstracted away into a function that accepts a delimited string and a value as inputs and returns a boolean. Second, if the Array.IndexOf approach is chosen, PLEASE read the documentation. This is NOT vb6. The result of Array.IndexOf is ONE LESS than the array's lower bound if an item is not found. This is a huge split from the -1 result from VB6's InStr. > If Not (Array.IndexOf(PatternArray, TestItem.ToString) = -1) Then -BooGhostInAK wrote:
> The result of Array.IndexOf is ONE LESS than the array's lower bound Does that mean that we can still /have/ arrays whose lower bound is > if an item is not found. /not/ zero? I thought we'd consigned those to History and that /every/ array just started at zero now. Or am I just deluding myself (again)? Regards, Phill W. Hello Phill W.,
Indeed Phil, you can have array's whose lower bounds are non-zero. Check out the MSDN doco for Array.CreateInstance. -Boo Show quoteHide quote > GhostInAK wrote: > >> The result of Array.IndexOf is ONE LESS than the array's lower bound >> if an item is not found. >> > Does that mean that we can still /have/ arrays whose lower bound is > /not/ zero? I thought we'd consigned those to History and that > /every/ array just started at zero now. > > Or am I just deluding myself (again)? > > Regards, > Phill W. Jim Wooley
http://devauthority.com/blogs/jwooley/default.aspx Show quoteHide quote > Hello Jimbo, I understand how the lower bound of the array can be something other than > > I would like to point out that Larry Lard is quite correct in his > assertion that whichever method is chosen it needs to be abstracted > away into a function that accepts a delimited string and a value as > inputs and returns a boolean. > > Second, if the Array.IndexOf approach is chosen, PLEASE read the > documentation. > This is NOT vb6. The result of Array.IndexOf is ONE LESS than the > array's > lower bound if an item is not found. This is a huge split from the -1 > result > from VB6's InStr. > >> If Not (Array.IndexOf(PatternArray, TestItem.ToString) = -1) Then >> > -Boo > 0. I was trying to isolate the time for parsing on the timers rather than including the time for determining the lowerbound on each iteration. I did find that I forgot to reset the stopwatch after each test, so the timing results are cumulative rather than per test. I revised the test and still found that the Contains method was the slowest, but not my as much as originally thought. I also added a couple other tests to use your method of testing the LowerBound on each iteration (method 1.1) as well as pulling it and putting it into a variable outside of the loop (method 1.2). here are the results for 1000 iterations: Testing against -1: 25093 testing against Array.GetLowerBound: 28384 Using a named variable outside of the loop and using Array.GetLowerBound: 22342 I am not surprised with the results of the second test. I am somewhat surprised that the third is faster than the second method even though it would appear that you are adding to the memory overhead. It is more readable and maintainable. The source for these three tests are below. I welcome alternative methods to test as well. Jim Wooley http://devauthority.com/blogs/jwooley/default.aspx Console.Write("method1: ") sw.Start() For iterations As Integer = 1 To IterationCount For TestItem As Integer = 0 To 10 If Not (Array.IndexOf(PatternArray, TestItem.ToString) = -1) Then CountSuccess += 1 End If Next Next sw.Stop() Console.WriteLine(sw.ElapsedTicks.ToString) sw.Reset() Console.Write("method1.1: ") sw.Start() For iterations As Integer = 1 To IterationCount For TestItem As Integer = 0 To 10 If Not (Array.IndexOf(PatternArray, TestItem.ToString) = (PatternArray.GetLowerBound(0) - 1)) Then CountSuccess += 1 End If Next Next sw.Stop() Console.WriteLine(sw.ElapsedTicks.ToString) sw.Reset() Console.Write("method1.2: ") sw.Start() Dim NotFoundKey As Integer = (PatternArray.GetLowerBound(0) - 1) For iterations As Integer = 1 To IterationCount For TestItem As Integer = 0 To 10 If Not (Array.IndexOf(PatternArray, TestItem.ToString) = NotFoundKey) Then CountSuccess += 1 End If Next Next sw.Stop() Console.WriteLine(sw.ElapsedTicks.ToString) sw.Reset() method1: 25093 method1.1: 28384 method1.2: 22342 method2: 33875 method3: 32627 Total success: 45000 Total should equal: 27000 On 2006-06-08, Phill W. <p-.-a-.-w-a-r-d@o-p-e-n-.-a-c-.-u-k> wrote:
Show quoteHide quote > Larry Lard wrote: IMHO, yes that's horribly wrong.>> GhostInAK wrote: > >>> Dim tIDStr As String = "1,2,3,4,5,6,7,8,9" >>> Dim tIDs() As String = tIDStr.Split(",") >>> If (tIDs.GetLowerBound(0) - 1) = Array.IndexOf(tIDs, "3") Then >>> >>> There are of course other methods. > > OK, I'm [probably] going to rekindle a Religious War here but, > hopefully, learn something at the same time ... > > In VB6, I'd have done [something like] this: > > Dim sSearch As String = "1,2,3,4,5,6,7,8,9" > Dim sTarget As String = "4" > > If ("," & sSearch & ",").IndexOf("," & sTarget & ",") > -1 Then > . . . > End If > > Is this horribly, horribly wrong in our Brave New World? It works, which is a plus, but if you're reading that code in a year's time I can't believe you won't stop to figure out what's going on. The array option isn't bad, but I must admit I find array syntax cumbersome. It's much easier to simply create a list.... Dim allowedIds as new List(Of String)(sSearch.Split(","c)) if allowedIds.Contains(sTarget) Then ..... Worrying about efficient code here is probably counterproductive. It's extremely unlikely that this simple lookup is going to be your bottleneck, especially if you're reading the list of ids from disk. Go for what's most readable. "hazz" <hazz@sonic_net> schrieb: <URL:http://groups.google.de/group/microsoft.public.dotnet.languages.vb/msg/d7938dd8bdbd5335>>I need to get a set of comma delimited client ids from a config file to >test against while running through my main processing loop. > If a given clientid matches any of the ids in the list, I don't want to > send email to them. -- M S Herfried K. Wagner M V P <URL:http://dotnet.mvps.org/> V B <URL:http://classicvb.org/petition/> I have a wealth of excellent ideas to study. Thank you everyone!
Appreciately, Greg Show quoteHide quote "hazz" <hazz@sonic_net> wrote in message news:OxDH4npiGHA.1936@TK2MSFTNGP04.phx.gbl... >I need to get a set of comma delimited client ids from a config file to >test against while running through my main processing loop. > If a given clientid matches any of the ids in the list, I don't want to > send email to them. > > What is the best way to code that? I was thinking of the idea of if > currentClientID is not in the list of these clientids, then ..... > > Thanks, > Greg > |
|||||||||||||||||||||||