B4J Question Using To in Select Cases?

Hi,

I am attempting to use a reserved word that doesn't seem to exist in B4x, the To keyword, in this context:

B4X:
Select Case SomeChar
 Case "A" To "Z", "a" To "z"
  ' Identifies a keyword

End Select

But in this case it the compiler throws errors if I attempt to do anything but this:
B4X:
Select Case SomeChar
 Case "A", "B","C", ... "Z", "a", "b", "c", ... "z"
  ' Identifies a keyword

End Select

What is an alternative to this that I can use? I would assume that it would have to be something like RegEx or something like that... but I'm unsure how to use it like the To keyword for a specific case?

Thanks,
 

Heuristx

Active Member
Licensed User
Longtime User
Hi,

I am attempting to use a reserved word that doesn't seem to exist in B4x, the To keyword, in this context:

B4X:
Select Case SomeChar
 Case "A" To "Z", "a" To "z"
  ' Identifies a keyword

End Select

But in this case it the compiler throws errors if I attempt to do anything but this:
B4X:
Select Case SomeChar
 Case "A", "B","C", ... "Z", "a", "b", "c", ... "z"
  ' Identifies a keyword

End Select

What is an alternative to this that I can use? I would assume that it would have to be something like RegEx or something like that... but I'm unsure how to use it like the To keyword for a specific case?

Thanks,
Select is just a shortcut for If.
If it doesn't cut it short, why sweat? Just use the next available tool.
 
Upvote 0
Select Case handles multiple right hand expressions to a comparator, a shortcut to if like you suggested here. I prefer Select Case to using multiple If... Else If expressions.

I don't understand what exactly you mean by 'if it doesn't cut it short'?

Could you elaborate on what the next available tool is?

Thanks for your reply so far,
 
Upvote 0

Heuristx

Active Member
Licensed User
Longtime User
Select Case handles multiple right hand expressions to a comparator, a shortcut to if like you suggested here. I prefer Select Case to using multiple If... Else If expressions.

I don't understand what exactly you mean by 'if it doesn't cut it short'?

Could you elaborate on what the next available tool is?

Thanks for your reply so far,

Sure, it is a shortcut for If. But in this case it is not a shortcut, because there is no "To". The next available tool is If.
It is not a good idea to select the tool first and try to adjust the problem to it.
You can sweat out something like:

B4X:
Select True
  Case something > Limit1 And Something < Limit2
     ...
 End Select

but it is unnatural. If you would have to use it many times, you can also write some function like

Sub Between(Val As ..., MinLimit As ..., MaxLimit as ...) As Boolean

or you can call it Sub InRange. I guess we could come up with a lot of different ways. But for this problem, If is the natural tool, why fight it?
 
Upvote 0

Heuristx

Active Member
Licensed User
Longtime User
Here is a general InRange function. You don't have to use multiple if's!
In exchange, you do have to type lots of brackets. This is what happens when we try to generalize a solution. It's always a trade.

InRange:
'Usage:
Log(InRange(12, Array(CreateRange(0, 11), 13, CreateRange(8, 11))))
Log(InRange(12, Array(CreateRange(0, 11), 13, CreateRange(8, 20))))
Log(InRange("c", Array(CreateRange("a", "b"), "z", CreateRange("b", "c"))))
Log(InRange("c", Array(CreateRange("a", "b"), "z", CreateRange("f", "m"))))

Sub Process_Globals
   Type TRange(Low As Object, High As Object)
End Sub

Public Sub CreateRange(ALow As Object, AHigh As Object) As TRange
   Dim Result As TRange
   Result.Initialize
   Result.Low = ALow
   Result.High = AHigh
   Return Result  
End Sub

Public Sub InRange(Val As Object, Ranges() As Object) As Boolean
  If Val Is String Then
     For Each O As Object In Ranges
       If O Is TRange Then
         If O.As(TRange).Low.As(String).CompareTo(Val) <= 0 And O.As(TRange).High.As(String).CompareTo(Val)    >= 0 Then
           Return True
         Else If O = Val Then
           Return True  
         End If 'Match or not
       End If 'O is Range
     Next
  Else
     For Each O As Object In Ranges
       If O Is TRange Then
         If O.As(TRange).Low <= Val And O.As(TRange).High >= Val Then
           Return True
         Else If O = Val Then
           Return True
         End If 'Match or not
       End If 'Range or not
     Next
  End If 'String or not
  Return False
End Sub
 
Last edited:
Upvote 0

Heuristx

Active Member
Licensed User
Longtime User
You are missing a couple of End If in Public Sub InRange(
I like the approach. It is very good.
You are right!
I don't know how it happened, I copied the code from B4J where it compiles and works, so obviously it was lost when I copied it. How? I don't know.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Actually, I think this code below has too many End If's
B4X:
Public Sub InRange(Val As Object, Ranges() As Object) As Boolean
  If Val Is String Then
     For Each O As Object In Ranges
       If O Is TRange Then
         If O.As(TRange).Low.As(String).CompareTo(Val) <= 0 And O.As(TRange).High.As(String).CompareTo(Val)    >= 0 Then
           Return True
         Else If O = Val Then
           Return True 
         End If 'Match or not
       End If 'O is Range
     Next
  Else
     For Each O As Object In Ranges
       If O Is TRange Then
         If O.As(TRange).Low <= Val And O.As(TRange).High >= Val Then
           Return True
         Else If O = Val Then
           Return True
         End If 'Match or not
       End If 'Range or not
     Next
  End If 'String or not
  Return False
End Sub

The If O.As(TRange) statements should be one liners
B4X:
Public Sub InRange(Val As Object, Ranges() As Object) As Boolean
    If Val Is String Then
        For Each O As Object In Ranges
            If O Is TRange Then
                If O.As(TRange).Low.As(String).CompareTo(Val) <= 0 And O.As(TRange).High.As(String).CompareTo(Val) >= 0 Then Return True
            Else If O = Val Then
                Return True
            End If 'Match or not
        Next
    Else
        For Each O As Object In Ranges
            If O Is TRange Then
                If O.As(TRange).Low <= Val And O.As(TRange).High >= Val Then Return True
            Else If O = Val Then
                Return True
            End If 'Match or not
        Next
    End If 'String or not
    Return False
End Sub
 
Last edited:
Upvote 0

Heuristx

Active Member
Licensed User
Longtime User
Actually, I think this code below has too many End If's
B4X:
Public Sub InRange(Val As Object, Ranges() As Object) As Boolean
  If Val Is String Then
     For Each O As Object In Ranges
       If O Is TRange Then
         If O.As(TRange).Low.As(String).CompareTo(Val) <= 0 And O.As(TRange).High.As(String).CompareTo(Val)    >= 0 Then
           Return True
         Else If O = Val Then
           Return True 
         End If 'Match or not
       End If 'O is Range
     Next
  Else
     For Each O As Object In Ranges
       If O Is TRange Then
         If O.As(TRange).Low <= Val And O.As(TRange).High >= Val Then
           Return True
         Else If O = Val Then
           Return True
         End If 'Match or not
       End If 'Range or not
     Next
  End If 'String or not
  Return False
End Sub
[code]

The If O.As(TRange) statements should be one liners
[code]
Public Sub InRange(Val As Object, Ranges() As Object) As Boolean
    If Val Is String Then
        For Each O As Object In Ranges
            If O Is TRange Then
                If O.As(TRange).Low.As(String).CompareTo(Val) <= 0 And O.As(TRange).High.As(String).CompareTo(Val) >= 0 Then Return True
            Else If O = Val Then
                Return True
            End If 'Match or not
        Next
    Else
        For Each O As Object In Ranges
            If O Is TRange Then
                If O.As(TRange).Low <= Val And O.As(TRange).High >= Val Then Return True
            Else If O = Val Then
                Return True
            End If 'Match or not
        Next
    End If 'String or not
    Return False
End Sub
You are right, too.
 
Upvote 0

Heuristx

Active Member
Licensed User
Longtime User
Both code snippets in post #8 by @OliverA are identical and yield the same result.
Try to copy them into B4J or B4A and you will see that hey are different.
The Else in line 7 in the first snippet means something totally different than the Else in line 6 in the second snippet.
I created the mess in Snippet 1 by ignoring that the Return True was on a different line, so the If clause was no longer a single-line If.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Both code snippets in post #8 by @OliverA are identical and yield the same result
Try:
B4X:
Log(InRange("z", Array(CreateRange("a", "b"), "z", CreateRange("f", "m"))))
The first should yield false, the second true.
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Log(InRange("z", Array(CreateRange("a", "b"), "z", CreateRange("f", "m"))))
I was trying with these two examples. In both cases, I get the same result for both:
B4X:
Log(InRange("z", Array(CreateRange("a", "b"))))   'false
 Log(InRange("m", Array(CreateRange("a", "z"))))   'true
Isn't that a proper application. By the way, I am using B4A with B4Xpages
 
Upvote 0

Heuristx

Active Member
Licensed User
Longtime User
The critical code makes a difference between a TRange structure and a simple string. Your test uses only the Range.
Look at OliverA's code, it has both.
 
Upvote 0

Heuristx

Active Member
Licensed User
Longtime User
Shouldn't we move this discussion to some other thread? We are kind of hijacking the original post. What is the best practice?
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Could you or Oliver please try your approach for this below example and tell me whether true or false and explain your finding. I think there is still something I am missing:
B4X:
Log(InRange("america", Array(CreateRange("australia", "france")  , "america", CreateRange( "algeria", "azerbajan") )))
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Could you or Oliver please try your approach for this below example and tell me whether true or false and explain your finding. I think there is still something I am missing:
B4X:
Log(InRange("america", Array(CreateRange("australia", "france")  , "america", CreateRange( "algeria", "azerbajan") )))
True, but you are using the wrong test case. The reason this is True is that "america" falls within the range of "algeria" and "azerbaian". Try

B4X:
Log(InRange("america", Array(CreateRange("australia", "france")  , "america", CreateRange( "angola", "azerbajan") )))

Note: For anyone following this, use the InRange in the first code block of post #8. The reason this fails is that particular code only checks items in the Ranges() array that are a TObject. If the item in the Ranges() array is a String, then no testing is done (no matter if Val itself is a String or not).
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
use the InRange in the first code block of post #8.
Which block in post #8 are you supposed to use to get the proper result for these two:
B4X:
Log(InRange("america", Array(CreateRange("australia", "france")  , "america", CreateRange( "angola", "azerbajan") )))
    Log(InRange("america", Array(CreateRange("algeria", "azerbajan")   )))
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Which block in post #8 are you supposed to use to get the proper result for these two:
The second block is the corrected block. Note that is just one way to correct the first block (using single line If statements). Here is a version that avoids all single line IF statements and therefore may be visually clearer:
B4X:
Public Sub InRange(Val As Object, Ranges() As Object) As Boolean
    If Val Is String Then
        For Each O As Object In Ranges
            If O Is TRange Then
                If O.As(TRange).Low.As(String).CompareTo(Val) <= 0 And O.As(TRange).High.As(String).CompareTo(Val)    >= 0 Then
                    Return True
                End If
            Else ' O is not a TRange
                If O = Val Then    
                    Return True
                End If
            End If
        Next
    Else ' Val is not a String
        For Each O As Object In Ranges
            If O Is TRange Then
                If O.As(TRange).Low <= Val And O.As(TRange).High >= Val Then
                    Return True
                End If
            Else ' O is not a TRange
                If O = Val Then
                    Return True
                End If
            End If 
        Next
    End If
    Return False
End Sub
 
Upvote 0
Top