Android Code Snippet PyRange() - Python index operator [a:b]

PyRange() - Obtain any object or range of objects (or characters from a String), using square brackets, just like in Python.


Usage:
B4X:
PyRange(object, "[a:b]")  'From  (a) to (b)
PyRange(object, "[a:]")   'From  (a)
PyRange(object, "[:b]")   'Up to (b)
PyRange(object, "[-a:]")  'From  (lenght/size minus (a))
PyRange(object, "[:-b]")  'Up to (lenght/size minus (b))
PyRange(object, "[i]")    'At index (i)

'Where 'a' represents the lower-bound, 'b' the higher-bound and 'i' an index


Snippet:
B4X:
Sub PyRange(obj As Object, range As String) As Object
    range = range _
        .Replace("[", "") _
        .Replace("]", "") _
        .Replace(" ", "")
    If range == ":" Then Return obj
    '-------------------------------------------------
    Dim objType = GetType(obj) As String
    Dim len As Int
    If objType = "java.lang.String" Then
        Dim str = obj As String
        len = str.Length
    Else If objType.StartsWith("[") Then
        Dim arr() = obj As Object
        len = arr.Length
    Else If objType = "java.util.ArrayList" Then
        Dim lst = obj As List
        len = lst.Size
    End If
    '-------------------------------------------------
    If range.Contains(":") Then
        Dim comps() = Regex.Split(":", range) As String
        Dim from = 0 As Int : Dim upTo = len As Int
        If comps(0).Length > 0 Then
            If comps(0) < 0                    _
            Then from = Max(0, len + comps(0)) _
            Else from = Min(comps(0), len)
        End If
        If comps.Length > 1 And comps(1).Length > 0 Then
            If comps(1) < 0                    _
            Then upTo = Max(0, len + comps(1)) _
            Else upTo = Min(comps(1), len)
        End If
        If objType = "java.lang.String" Then
            If from > upTo Then Return ""
            Return str.SubString2(from, upTo)
        Else If objType.StartsWith("[") Then
            If from > upTo Then Return Array As Object()
            Dim newArr(upTo - from) As Object
            For i = from To upTo - 1
                newArr(i - from) = arr(i)
            Next
            Return newArr
        Else If objType = "java.util.ArrayList" Then
            Dim newLst As List : newLst.Initialize
            For i = from To upTo - 1
                newLst.Add(lst.Get(i))
            Next
            Return newLst
        End If
        Return Null
    Else
        Dim index = range As Int
        If index < 0 Then index = len + index _
        Else index = Min(index, len)
        Try
            If objType = "java.lang.String" Then
                Return str.CharAt(index)
            Else If objType.StartsWith("[") Then
                Return arr(index)
            Else If objType = "java.util.ArrayList" Then
                Return lst.Get(index)
            End If
        Catch
            Log("IndexError: string index out of range")
        End Try
        Return Null
    End If
End Sub


Examples:
B4X:
Dim strArray() = Array As String("I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII") As String
Dim strList As List : strList.Initialize : strList.Add("A") : strList.Add("B") : strList.Add("C") : strList.Add("D")

'Obtain substring from string
Log("A: >" & PyRange("Hello World", "[1:-1]") & "<")

'Obtain character from string
Log("B: >" & PyRange("Hello World", "[6]") & "<")

'Obtain array from array (any type)
Dim arr() = PyRange(strArray, "[4:]") As Object
For Each item As String In arr
    Log("C: >" & item & "<")
Next

'Obtain list from list
Dim lst = PyRange(strList, "[:-2]") As List
For Each item As String In lst
    Log("D: >" & item & "<")
Next

'Obtain item from list
Log("E: >" & PyRange(strList, "[-3]") & "<")

'Obtain item from array
Log("F: >" & PyRange(strArray, "[5]") & "<")

'Obtain item from list (error)
Log("G: >" & PyRange(strList, "[-99]") & "<")

'Obtain item from array (error)
Log("H: >" & PyRange(strArray, "[99]") & "<")


Stress test:
Both programs yield exactly the same output.
Verified using a diff tool (Meld).
B4X:
'B4X Code:
'==================================
For aaa = -12 To 12
    For bbb = -12 To 12
        Log("[" & aaa & ":" & bbb & "] >" & PyRange("0123456789", "[" & aaa & ":" & bbb & "]") & "<")
    Next
Next

For aaa = -12 To 12
    Log("[" & aaa & ":] >" & PyRange("0123456789", "[" & aaa & ":]") & "<")
Next

For aaa = -12 To 12
    Log("[:" & aaa & "] >" & PyRange("0123456789", "[:" & aaa & "]") & "<")
Next

Log("[:] >" & PyRange("0123456789", "[:]") & "<")

B4X:
#Python Code:
#==================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

a = '0123456789'

for x in range(-12,13):
        for y in range(-12,13):
                print '[' + str(x) + ':' + str(y) + '] >' + a[x:y] + '<'

for x in range(-12,13):
        print '[' + str(x) + ':] >' + a[x:] + '<'

for x in range(-12,13):
        print '[:' + str(x) + '] >' + a[:x] + '<'

print '[:] >' + a[:] + '<'

upload_2017-10-4_17-7-34.png
 
Last edited:

wonder

Expert
Licensed User
Longtime User
The code that checks the object type is not required.

Just set the parameter type to List. B4X automatically converts arrays to lists.
Nonetheless, if I want the return the same type (passed array returns array, passed list returns list) that was passed as a parameter, I still need that check, right?
 
Top