Manuel Santi
Manuel Santi

Reputation: 1132

Python modify list of list value based on previous value

In my project I have a list like this one:

varlist = [['Variables', ''], ['bs_${FORM_URL}', 'SC'], ['${FORM_URL}', 'http://www.example.com'], ['bs_${NUM_RAND}', 'RN'], ['${NUM_RAND}', '0-200'], ['bs_${TEXT}', 'SC'], ['${TEXT}', 'mytest']]

I have to check if there is a data with RN value and, if I found this, change next nested list value with a random value based on next list value. In my example there is a list with RN (['bs_${NUM_RAND}', 'RN']), well, I have to remove it and change next list value (['${NUM_RAND}', '0-200']) creating an int random between 0 and 200. I try like this:

p_oper = 'SC'        
for li in varlist:
    if li[0][0:3] == 'bs_':
        p_oper = li[1]
        varlist.remove(li)
    else:
        if p_oper == 'RN':
            num1 = int(li[1].split('-')[0].strip())
            num2 = int(li[1].split('-')[1].strip())
            li[1] = str(int(random.randint(num1, num2)))

At the end of my function the resulting list should be like this one:

[['Variables', ''], ['${FORM_URL}', 'http://www.example.com'], ['${NUM_RAND}', '42'], ['${TEXT}', 'mytext']]

but this does not work. Anyone has any idea about how I can manipulate my list of lists in that fashion?

Upvotes: 0

Views: 85

Answers (3)

r.ook
r.ook

Reputation: 13858

Instead of removing the items you might opt to strip out the "bs" sublists and create a new one instead:

varlist[0]] + [[v[0], str(random.randint(*map(int, v[1].split('-'))))] if bs[1] == 'RN' else v for bs, v in zip(varlist[1::2], varlist[2::2])]

# Result: 
[['Variables', ''], ['${FORM_URL}', 'http://www.example.com'], ['${NUM_RAND}', '4'], ['${TEXT}', 'mytest']]

This one liner can basically be rewritten to this:

l = [varlist[0]]
for bs, v in zip(varlist[1::2], varlist[2::2]):
    if bs[1] == 'RN':
        n, m = map(int, v[1].split('-'))
        l.append([v[0], str(random.randint(n, m))])
    else:
        l.append(v)

The zip function allows you to cross reference slices of the original varlist while effectively removing the "bs" sublists at the same time.

Upvotes: 2

Sébastien Lavoie
Sébastien Lavoie

Reputation: 897

This is happening because your indexes change once you delete items in your list of lists. An easy fix would be to maintain the state of the original list and make your modifications to a copy of that list like so:

import random

p_oper = 'SC'
new_varlist = varlist[:]  # Making a copy of the original list
for li in varlist:
    if li[0][0:3] == 'bs_':
        p_oper = li[1]
        new_varlist.remove(li)  # Removing the item in the new list only
    else:
        if p_oper == 'RN':
            num1 = int(li[1].split('-')[0])
            num2 = int(li[1].split('-')[1])
            li[1] = str(int(random.randint(num1, num2)))

Now you have a working code and access to both lists that print exactly what you are looking for:

>>> print(varlist)

[['Variables', ''], ['bs_${FORM_URL}', 'SC'], ['${FORM_URL}', 'http://www.example.com'], ['bs_${NUM_RAND}', 'RN'], ['${NUM_RAND}', '90'], ['bs_${TEXT}', 'SC'], ['${TEXT}', 'mytest']]

>>> print(new_varlist)

[['Variables', ''], ['${FORM_URL}', 'http://www.example.com'], ['${NUM_RAND}', '90'], ['${TEXT}', 'mytest']]

If you want to keep your original list intact without modifying the list ['${NUM_RAND}', '0-200'], you could also make a deep copy. This is also easily done if you need this functionality:

from copy import deepcopy

p_oper = 'SC'
original_varlist = deepcopy(varlist)

# ...

Upvotes: 2

Vicrobot
Vicrobot

Reputation: 3988

Assuming that there is always two items in your list's sublists; it can be done this way:

import random

varlist = [['Variables', ''], ['bs_${FORM_URL}', 'SC'], ['${FORM_URL}', 'http://www.example.com'], ['bs_${NUM_RAND}', 'RN'], ['${NUM_RAND}', '0-200'], ['bs_${TEXT}', 'SC'], ['${TEXT}', 'mytest']]

for i,j  in enumerate(varlist):
    if 'RN' in j:
        varlist.remove(varlist[i])
        varlist[i][1] = random.randint(0, 200)

print(varlist)

Output: [['Variables', ''], ['bs_${FORM_URL}', 'SC'], ['${FORM_URL}', 'http://www.example.com'], ['${NUM_RAND}', 147], ['bs_${TEXT}', 'SC'], ['${TEXT}', 'mytest']]

Upvotes: 1

Related Questions