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

wonder

Expert
Licensed User
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
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