Split strings w/ different patterns into consistent fields

Viewed 48

I have a set of strings that each follow one of a handful of patterns:

# where each 'no.' is some different numeric value, possibly w/ scientific notation
no.1 <= some text = no.2 <= no.3
some text = no.4
no.5 <= some text = no.6
some text = no.7 <= no.8

The consistent thing is the presence of the <= and = signs, in one of those combinations of orders.

I need to separate these strings, filling in None (or np.nan) where a numeric value could be but isn't present. In other words, I'd like each string to yield four distinct values - one containing some text and the other three containing the [up to] three no. values or None if they're not there. So:

no.1 <= some text = no.2 <= no.3
    -> [no.1, some text, no.2, no.3]
some text = no.4
    -> [None, some text, no.4, None]
no.5 <= some text = no.6
    -> [no.5, some text, no.6, None]
some text = no.7 <= no.8
    -> [None, some text, no.7, no.8]

Using split() on '<=' or '=' will separate the values, but if there are fewer than four values, it isn't very clear which pattern it was. I can use a bunch of if-else conditionals trying different splits, which seems to work but is very inelegant:

lines = [
    "0.5 <= First variable = 0.6  <= 1.5", 
    "Second variable = 0.483983", 
    "0.05 <= Third variable = 0.14897", 
    "Fourth variable = 0.1  <= 1"
]

outlines = []
for line in lines:
    out = []
    if '=' in line.split('<=')[0]:
        out.append(None)
        out.append(line.split('<=')[0].split('=')[0])
        out.append(line.split('<=')[0].split('=')[1])
    else:
        out.append(line.split('<=')[0])
        out.append(line.split('<=')[1].split('=')[0])
        out.append(line.split('<=')[1].split('=')[1])
    if '=' in line.split('<=')[-1]:
        out.append(None)
    else:
        out.append(line.split('<=')[-1])
    outlines.append(out)

outlines
> [['0.5 ', ' First variable ', ' 0.6  ', ' 1.5'],
 [None, 'Second variable ', ' 0.483983', None],
 ['0.05 ', ' Third variable ', ' 0.14897', None],
 [None, 'Fourth variable ', ' 0.1  ', ' 1']]

Is there a streamlined way to handle this task? With or without regex?

1 Answers

The function below works, it splits for the equal sign first so that you can then differentiate between cases with the split of the minus equal:

def func(text):
    list_p = [None]*4
    for i,p in enumerate(text.split(" = ")):
        subps = p.split(" <= ")
        list_p[i+1] = subps[-1] #fill in 'required' values at indexes 1 & 2 
        if len(subps) == 2: list_p[i*3]= subps[-2] # fill in 'optional' values at indexes 0 & 3
    return list_p

with

strings = ["no.1 <= some text = no.2 <= no.3", "some text = no.4", 
           "no.5 <= some text = no.6", "some text = no.7 <= no.8"]
for text in strings : print(func(text))

it prints

['no.1', 'some text', 'no.2', 'no.3']
[None, 'some text', 'no.4', None]
['no.5', 'some text', 'no.6', None]
[None, 'some text', 'no.7', 'no.8']
Related