简体   繁体   中英

Iterate over Python list, preserving structure of embedded lists

Python newbie here. I'm trying to perform a basic function on a list containing lists of various lengths. Within these lists are tuples containing pairs of elements that I intend to use as ranges. I want to convert these elements into integers, and then create a new tuple with the integers, followed by 2 , which will represent the iterator.

I want l :

l = [[('100', '200'), ('300', '400'), ('500', '600')], [('100', '200')], [('100', '200')]]

To be replaced by l_upd

l_upd = [[(100, 200, 2), (300, 400, 2), (500, 600, 2)], [(100, 200, 2)], [(100, 200, 2)]]

This obviously doesn't work (and I couldn't figure out how to get the 2 placed as an element:

l1 = []
l2 = []

for pairs in l:
    for pair in pairs:
        l1.append(int(i[0]))
        l2.append(int(i[1]))

l_upd = zip(l1, l2)

EDIT: I would prefer to not use a list comprehension method, because I need to include an if , else statement. Some of the elements contain letters, and some are empty.

Something like the following is needed for these exceptions:

for pair in pairs:
    if pair[0].isdigit():
        addr_from.append(int(i[0]))
    elif pair[0].isalnum() is True and pair[0].isdigit is False:
        addr_from.append(re.sub(r'((?:[A-Z].*?)?(?:\d.*?)?[A-Z]+)(\d+)',r'\1%\2',pair[0]))
    else:
        addr_from.append(pair[0])
    if pair[1].isdigit():
        addr_to.append(int(i[1]) + 2)
    elif pair[1].isalnum() is True and pair[1].isdigit is False:
        addr_to.append(re.sub(r'((?:[A-Z].*?)?(?:\d.*?)?[A-Z]+)(\d+)',r'\1%\2',pair[1]))

you could write some recursive function to do the job(which means the function can deal with any level of nested lists unless it hits maximum recursion depth)

def addtwo(lst):
   new_lst = []
   for item in lst:
     if isinstance(item, list):
       new_lst.append(addtwo(item))
     elif isinstance(item, tuple):
       new_lst.append(item + (2,))

   return new_lst

l = [[('100', '200'), ('300', '400'), ('500', '600')], [('100', '200')], [('100', '200')]]
print addtwo(l)

#[[('100', '200', 2), ('300', '400', 2), ('500', '600', 2)], [('100', '200', 2)], [('100', '200', 2)]]

Using list comprehensions:

>>> [[tuple(map(int, pair)) + (2,) for pair in pairs] for pairs in l]
[[(100, 200, 2), (300, 400, 2), (500, 600, 2)], [(100, 200, 2)], [(100, 200, 2)]]

Or without the map:

>>> [[(int(a), int(b), 2) for a, b in pairs] for pairs in l]
[[(100, 200, 2), (300, 400, 2), (500, 600, 2)], [(100, 200, 2)], [(100, 200, 2)]]

Edit

Even with further checks, you can still use list comprehension. I assume that the if/else section you have added to your question should be applied to every pair, and the resulting tuple would be (addr_from, addr_to, 2) then, right?

def processPair(a, b):
    if a.isdigit():
        a = int(a)
    elif a.isalnum():
        a = re.sub(r'((?:[A-Z].*?)?(?:\d.*?)?[A-Z]+)(\d+)', r'\1%\2', a)
    if b.isdigit():
        b = int(b) + 2
    elif b.isalnum():
        b = re.sub(r'((?:[A-Z].*?)?(?:\d.*?)?[A-Z]+)(\d+)', r'\1%\2', b)
    return (a, b, 2)

Here I have defined a function that processes the tuple (a, b) as you did in your question. Note that I have changed it to just modify the values of the variables and return a finished tuple (with the added 2) instead of appending it to some global list.

I have also simplified it a bit. a.isdigit() is True is the same as a.isdigit() as that already returns a boolean value. Same for a.isdigit() == False , which is the same as not a.isdigit() . In that situation you can also remove redundant checks. After checking a.isdigit() on the if , you do not need to check its opposite on the elif ; it is guaranteed to be false, as you have already checked it before.

That being said, when you have said function, you can then use list comprehensions again, to get your output. Of course with your example l , this is a bit boring:

>>> [[processPair(*pair) for pair in pairs] for pairs in l]
[[(100, 202, 2), (300, 402, 2), (500, 602, 2)], [(100, 202, 2)], [(100, 202, 2)]]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM