Android Question Select Case

Sergey_New

Well-Known Member
Licensed User
Longtime User
Is it possible to use a variable in a Select Case procedure instead of listing values?
B4X:
Select Case "c"
    Case "a","b","c","d","e"
        ...
    Case Else
        ...
End Select
 

emexes

Expert
Licensed User
Yes, I wanted to replace "a","b","c","d","e" with a variable.
Still no.

But if you're working with single characters, you can do a quick "multi-way if" using String.Contains eg:

B4X:
Dim MustBeOneOfThese As String = "abcde"

If MustBeOneOfThese.Contains("c") Then    'equivalent to Select Case "c" : Case "a", "b", "c", "d", "e"
    Log("Your letter c is included in your variable list of desirable characters " & MustBeOneOfThese)
Else
    Log("Your letter c does not pass the test")
End If

For L = 1 To 26
    Dim OrdinalSuffix As String = "th"
    Select Case L Mod 10
        Case 1: OrdinalSuffix = "st"
        Case 2: OrdinalSuffix = "nd"
        Case 3: OrdinalSuffix = "rd"
    End Select
   
    Log("The letter " & Chr(96 + L) & " is the " & L & OrdinalSuffix & " letter of the (english) alphabet.")
Next

Log output:
Waiting for debugger to connect...
Program started.
Your letter c is included in your variable list of desirable characters abcde
The letter a is the 1st letter of the (english) alphabet.
The letter b is the 2nd letter of the (english) alphabet.
The letter c is the 3rd letter of the (english) alphabet.
The letter d is the 4th letter of the (english) alphabet.
The letter e is the 5th letter of the (english) alphabet.
The letter f is the 6th letter of the (english) alphabet.
The letter g is the 7th letter of the (english) alphabet.
The letter h is the 8th letter of the (english) alphabet.
The letter i is the 9th letter of the (english) alphabet.
The letter j is the 10th letter of the (english) alphabet.
The letter k is the 11st letter of the (english) alphabet.
The letter l is the 12nd letter of the (english) alphabet.
The letter m is the 13rd letter of the (english) alphabet.
The letter n is the 14th letter of the (english) alphabet.
The letter o is the 15th letter of the (english) alphabet.
The letter p is the 16th letter of the (english) alphabet.
The letter q is the 17th letter of the (english) alphabet.
The letter r is the 18th letter of the (english) alphabet.
The letter s is the 19th letter of the (english) alphabet.
The letter t is the 20th letter of the (english) alphabet.
The letter u is the 21st letter of the (english) alphabet.
The letter v is the 22nd letter of the (english) alphabet.
The letter w is the 23rd letter of the (english) alphabet.
The letter x is the 24th letter of the (english) alphabet.
The letter y is the 25th letter of the (english) alphabet.
The letter z is the 26th letter of the (english) alphabet.
Program terminated (StartMessageLoop was not called).
 
Upvote 0

emexes

Expert
Licensed User
Yes, I wanted to replace "a","b","c","d","e" with a variable.

You could do it with an Array or List of the Case values too eg:

B4X:
Dim CaseValues() As String = Array As String("a", "b", "c", "d", "e")

If CaseValues.As(List).IndexOf("c") <> -1 Then
    Log("The letter c is in your list of desirable characters.")
Else
    Log("Case Else goes here")
End If
Log output:
Waiting for debugger to connect...
Program started.
The letter c is in your list of desirable characters.
Program terminated (StartMessageLoop was not called).
 
Upvote 0

emexes

Expert
Licensed User
Forgot to point out that the Array or List method works with not just single characters, eg:

B4X:
Dim ExcellentMovies() As String = Array As String( _
    "DIE HARD", _
    "DIE HARD 2", _
    "DIE HARD WITH A VENGEANCE", _
    "LIVE FREE OR DIE HARD", _
    "A GOOD DAY TO DIE HARD" _
)

Dim ThinkingAboutWatching As String = "Live Free or Die Hard"

If ExcellentMovies.As(List).IndexOf(ThinkingAboutWatching.ToUpperCase) <> -1 Then    'equivalent to Select Case one-of-the-listed-movies
    Log("The movie """ & ThinkingAboutWatching & """ is an excellent choice.")
Else
    Log("Case Else goes here")
End If
Log output:
Waiting for debugger to connect...
Program started.
The movie "Live Free or Die Hard" is an excellent choice.
Program terminated (StartMessageLoop was not called).

You can hang sh*t on my movie favourites but you can't hang sh*t on the programming workarounds. 🍻
 
Last edited:
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Do you mean like
B4X:
Dim myVar As String = "Fred"
Dim myList as List = Array("Adam","Fred","John")
Select True
Case MyList.as(JavaObject).RunMethod("contains",array(myVar))
log("Fred found")
Case Else
log("Fred not found")
End Select
 
Upvote 0

emexes

Expert
Licensed User
Dim myList as List = Array("Adam", "Fred", "John")

This is cleaner than my two-step approach, although if the resulting List has a working .IndexOf method then I'd be inclined to use that directly as a poor man's .Contains.

Plus you still have the problem of having to include the selection variable within each Case except the Else. Not a problem if there is only one of those (like in all our examples here so far) but... if there is only one, then could just use a standard (non-inside-out) If-Then-Else.
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
Is it possible
Do you mean

Like Luca (I think) I'm interested to see an example more specific to the use case. Like, are we talking characters, strings, numbers or some combination of those? In contiguous ranges eg "a" to "e"? Upper, lower or mixed case? Odd or even or any numbers?

And does the list of Case values change during a run, or is it constant for every program run, or set once when the program starts and never changes after that?
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Plus you still have the problem of having to include the selection variable within each Case
Thats true , but if I coded it properly and not just as a quicky I would have like below which reduces the typing on each case line
B4X:
Dim myVar As String = "Fred"
Dim myList as List = Array("Adam","Fred","John")
Select True
Case IsIn(myList,myVar)
log("Fred found")
Case Else
log("Fred not found")
End Select
...

Sub IsIn(theList as JavaObject, v as Object) as Boolean
Return theList.RunMethod("contains",array(v))
End Sub
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
Don't forget B4XSet - I always do - but it may make things more elegant? or not?

B4X:
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1

    Dim boys As B4XSet = makeSet(Array("Adam","Fred","John"))
    Dim girls As B4XSet = makeSet(Array("Jane", "Mary","Susan","Annie"))
    Dim person() As String = Array As String("Fred", "Mary", "Billy")
    For i = 0 To person.Length - 1
        Select True
            Case boys.Contains(person(i))
                Log(person(i) & " found in " & boys.AsList)
            Case girls.Contains(person(i))
                Log(person(i) & " found in " & girls.AsList)
            Case Else
                Log(person(i) & " not found")
        End Select
    Next

    'Log________   
    'Fred found in (ArrayList) [Adam, Fred, John]
    'Mary found in (ArrayList) [Jane, Mary, Susan, Annie]
    'Billy Not found
End Sub

Private Sub makeSet(ar() As Object) As B4XSet
    Dim set1 As B4XSet
    set1.Initialize
    For Each obj As Object In ar
        set1.Add(obj)
    Next
    Return set1   
End Sub
 
Upvote 0

Sergey_New

Well-Known Member
Licensed User
Longtime User
emexes, Daestrum, William Lancee thank you for your comments. I will try the suggested solutions and report the results.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Thats true , but if I coded it properly and not just as a quicky I would have like below which reduces the typing on each case line
B4X:
Dim myVar As String = "Fred"
Dim myList as List = Array("Adam","Fred","John")
Select True
Case IsIn(myList,myVar)
log("Fred found")
Case Else
log("Fred not found")
End Select
...

Sub IsIn(theList as JavaObject, v as Object) as Boolean
Return theList.RunMethod("contains",array(v))
End Sub
"Nice" but you don't need JavaObject, that works simply so:
B4X:
Case (myList.IndexOf(myVar) <> - 1)
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Don't forget B4XSet - I always do - but it may make things more elegant? or not?
I can't forget B4XSet, for the simple reason that to this day I still haven't "read" its advantages properly 😁 😊
Your source with Lists instead of B4XSets:
B4X:
    Dim lstBoys As List
    lstBoys.Initialize
    lstBoys.AddAll(Array As String("Adam","Fred","John"))
    
    Dim lstGirls As List
    lstGirls.Initialize
    lstGirls.AddAll(Array As String("Jane", "Mary","Susan","Annie"))

    Dim lstPerson As List
    lstPerson.Initialize
    lstPerson.AddAll(Array As String("Fred", "Mary", "Billy"))

    For i = 0 To lstPerson.Size - 1
        Select True
            Case (lstBoys.IndexOf(lstPerson.Get(i)) <> - 1)
                Log(lstPerson.Get(i) & " found in " & lstBoys)
            Case (lstGirls.IndexOf(lstPerson.Get(i)) <> - 1)
                Log(lstPerson.Get(i) & " found in " & lstGirls)
            Case Else
                Log(lstPerson.Get(i) & " not found.")
        End Select
    Next
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
@emexes mentioned ranges. I played with date ranges, but I'll stop now :)

B4X:
'Log____________
'1995-05-10 is Northern Spring        (Planting time)
'2024-06-24 is Northern Summer        (Midsummer Day)
'1946-10-02 is Northern Autumn        (Fall colors and a special day)
'1975-02-12 is Northern Winter        (Canada in February - Brrr)
'2024-12-25 is Northern Winter        (it is a White Christmas here)
'2024-12-20 is Northern Autumn        (tomorrow is Winter Solstace)
    
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1

    DateTime.DateFormat = "yyyy-MM-dd"
    Dim sampleDates() As String = Array As String("1995-05-10", "2024-06-24", "1946-10-02", "1975-02-12", "2024-12-25", DateTime.Date(DateTime.Now))
    For i = 0 To sampleDates.Length - 1
        Select True
            Case inDateRange(sampleDates(i), "*-01-01", "*-03-19")
                Log(sampleDates(i) & " is Northern Winter")
            Case inDateRange(sampleDates(i), "*-03-20", "*-06-20")
                Log(sampleDates(i) & " is Northern Spring")
            Case inDateRange(sampleDates(i), "*-06-21", "*-09-21")
                Log(sampleDates(i) & " is Northern Summer")
            Case inDateRange(sampleDates(i), "*-09-22", "*-12-20")
                Log(sampleDates(i) & " is Northern Autumn")
            Case inDateRange(sampleDates(i), "*-12-21", "*-12-31")
                Log(sampleDates(i) & " is Northern Winter")
        End Select
    Next
End Sub

Private Sub inDateRange(dt As String, fromDt As String, toDt As String) As Boolean
    Dim dtLong As Long = DateTime.DateParse(dt)
    Dim year As String = DateTime.GetYear(dtLong)
    Dim minIclDate As Long = DateTime.DateParse(fromDt.Replace("*", year))
    Dim maxIclDate As Long = DateTime.DateParse(toDt.Replace("*", year))
    Return dtLong >= minIclDate And dtLong <= maxIclDate
End Sub
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
I can't forget B4XSet, for the simple reason that to this day I still haven't "read" its advantages properly 😁 😊
I read (again) the tutorial about B4XCollections, more precisely about B4XSet (for now only this one).
I don't see any difference between B4XSet and List.
B4X:
    Dim xsetData As B4XSet
    xsetData = B4XCollections.CreateSet2(Array As String("A", "B", "C"))
    If xsetData.Contains("B") Then
        Log("xsetData contains B")
    Else
        Log("xsetData does not contain B")
    End If
What's the difference?
B4X:
    Dim lstData As List
    lstData.Initialize
    lstData.AddAll(Array As String("A", "B", "C"))
    If lstData.IndexOf("B") <> - 1 Then
        Log("lstData contains B")
    Else
        Log("lstData does not contain B")
    End If
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
@LucaMs

If we had a built-in createList (like createMap) there would not seem to be much difference.
But for large sets (thousands of items) 'B4XSet.contains' is faster than 'aList.IndexOf' - since it uses Maps, not Lists.
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
@LucaMs
At the cost of going off-topic, the CreateMap("kw1": 1, "kw2": 2) is nice since it allows for a variable length argument list.
CreateList("a", "b", "c") would be equally nice - I now mostly use a sub like that but it needs Array() as argument

Using my sub: CreateList(Array(("a", "b", "c"))

These are really small things to wish for - nothing like my wishes for Christmas.
 
Upvote 0
Top