Home > Blockchain >  One liner for poping list of lists based on condition
One liner for poping list of lists based on condition

Time:12-19

I've got the following lists:

leftoverbricks = [['purple1', 'y8', 'x0', 'y8', 'x1'], ['purple2', 'y6', 'y0', 'x8', 'y0'], ['purple3', 'z2', 'x8', 'z2', 'x0']]

and

startingbrick = ['purple3', 'z2', 1, 1]

I'd like to pop an element from leftoverbricks where startingbrick[0] matches first element of list of list from leftoverbricks, so leftoverbricks[][0]

I've created a function that works:

def removebrick(tempbrick, templist):
    reducedlist = templist
    for tempelement in reducedlist:
        if tempelement[0] == tempbrick[0]:
            reducedlist.pop(reducedlist.index(tempelement))
    return reducedlist

and which gives the correct result of:

reducedleftoverbricks = removebrick(startingbrick, leftoverbricks)

reducedleftoverbricks = [['purple1', 'y8', 'x0', 'y8', 'x1'], ['purple2', 'y6', 'y0', 'x8', 'y0']]

But it's not elegant. I hope such thing can be done with one liner and by mutating original leftoverbricks list rather than creating a new list variable reducedleftoverbricks. I did a few attempts at one liner list comprehension but so far failed.

CodePudding user response:

You can use a list comprehension to remove the elements from leftoverbricks that match the first element of startingbrick.

Example:

leftoverbricks = [['purple1', 'y8', 'x0', 'y8', 'x1'], ['purple2', 'y6', 'y0', 'x8', 'y0'], ['purple3', 'z2', 'x8', 'z2', 'x0']]
startingbrick = ['purple3', 'z2', 1, 1]

leftoverbricks = [brick for brick in leftoverbricks if brick[0] != startingbrick[0]]
print(leftoverbricks)

This will modify leftoverbricks in place, so you don't need to create a new list variable.

Otuput:

[['purple1', 'y8', 'x0', 'y8', 'x1'], ['purple2', 'y6', 'y0', 'x8', 'y0']]

CodePudding user response:

Personally, I'd consider using a filter. Note that the filter is going to be lazily evaluated, so you can evaluate the whole filter in the spot where you'd like the reduced list.

for brick in filter(lambda n: n[0] != startingbrick[0], leftoverbricks):
   do_more_work(brick)

CodePudding user response:

This would be a good use-case for filter().

e.g.,

leftoverbricks = [['purple1', 'y8', 'x0', 'y8', 'x1'], ['purple2', 'y6', 'y0', 'x8', 'y0'], ['purple3', 'z2', 'x8', 'z2', 'x0']]
startingbrick = ['purple3', 'z2', 1, 1]

def removebrick(tempbrick, templist):
    key, *_ = templist
    return list(filter(lambda v: v[0] != key, tempbrick))

print(removebrick(leftoverbricks, startingbrick))

Output:

[['purple1', 'y8', 'x0', 'y8', 'x1'], ['purple2', 'y6', 'y0', 'x8', 'y0']]

Note:

This does not modify the input list (leftoverbricks). If you want it to be destructive then just assign the return value from this function to the appropriate variable

  • Related