python – Separating data from string representation of objects, with added extras


Given a string representation of data, I want to extract the information into its corresponding object.

However,

If the string has “|” separators then these should be considered options and need to be picked at random.

If the string data has numbers shown as a range “1-10” then a random value should be chosen between the range. It should also preserve the numerical datatype i.e int or float

I.e

“(1-3,1,1)” returns either (1, 1, 1), (2, 1, 1) or (3, 1, 1)

“(0.2-0.4,1,1)” returns either (0.2, 1, 1), (0.3, 1, 1) or (0.4, 1, 1)

“foo|bar|foobar” returns either “foo”, “bar” or “foobar”

“(1-2,1,2)|”foo”|”bar”|(1,8-10,99)” could return :

“foo”,”bar”, (1, 1, 2), (2, 1, 2), (1, 8, 99), (1, 9, 99) or (1, 10, 99)

This is what I have and it works well. But I cant help think it could be achieved in a more concise way. Let me know what I could have done better.

import re
import random
import ast

def randomize_by_pipe(st_value):
    """
    Used to split strings with the pipe character and randomly choose and option.

    :param: st_value - (str)

    """
    if not st_value is None:
        st_arr = st_value.split("|")
        random.shuffle(st_arr)
        return st_arr(0)
    else:
        return st_value

def randomise_range(text):
    if text is None:
        return text
    else:
        matches = re.findall("d*.*d*-{1}d*.*d*",text)
        
        for match in matches:
            startingPos = 0
            position = text.find(match, startingPos)
            while True:
                position = text.find(match, startingPos)
                if position > -1:
                    txt = text(position:position+len(match))
                    txt = rand_no_from_string(txt)

                    new_text = text(0:position+len(match)).replace(match,str(txt))
                    text = new_text + text(position+len(match):)
                else:
                    break

        try:
            return ast.literal_eval(text)
        except ValueError:
            return text

def rand_no_from_string(txt):
    
    is_int = False
    txt_arr = txt.split("-")
    num_arr = (float(x) for x in txt_arr)
    if int(num_arr(0)) == num_arr(0):
        mul = 1
        is_int = True
    else:
        mul = 1000
    num_arr = (x*mul for x in num_arr)
    
    if num_arr(0) > num_arr(1):
        num_arr(1), num_arr(0) = num_arr(0), num_arr(1)
        
    val = random.randint(num_arr(0),num_arr(1))/mul
    return int(val) if is_int else val
    

Run with:

text="(108-100,0.25-0.75,100)|Foo|Bar|(123,234,234-250)"
randomise_range(randomize_by_pipe(text))