简体   繁体   中英

Set value of list item based on last defined value in list

I have a list of lists as follows.

ogList = [[a], [b], [], [], [c], [d], []]

I'd like each empty list to be populated like so, based on the last list which does have a value.

outputList = [[a], [b], [b], [b], [c], [d], [d]]

So far I have assembled the following.

copy = 0
for list in ogList:
    for list in list:
        for number in list:
            if number:
                copy = number
                print copy
            if not number:
                list.append(copy)

However append(copy) simply adds the value stored in copy to the second index of the list. Thus it occurred that I might use insert(0, copy), but this freezes up my system (infinite loop?). Here I am requesting assistance. How can I accomplish this?

I also greatly appreciate anyone willing to explain to this complete beginner what kinds of utter nonsense I might be employing here (like instantiating copy before the for loop?). Thank you everyone.

Try this:

ogList = [["a"], ["b"], [], [], ["c"], ["d"], []]

temp = ogList[0]
for i in range(1, len(ogList)):
    if ogList[i] == []:
        ogList[i] = temp
    else:
        temp = ogList[i]

If you use variables a, b, c, d in array instead of values "a", "b", "c", "d" , they must be assigned before array's assignment.

Don't use the same variable names in nested loops. That's why your program hangs.

a=1;b=2;c=3;d=4
ogList = [[a], [b], [], [], [c], [d], []]

copy = 0
for index, list in enumerate(ogList):
    if list: #if list is not empty
        copy = list[-1] # last element
    else:
        ogList[index] = [copy]
print(ogList)

In your code, you went one level too deep (used too many for loops).

Also in Python lists are mutable, so when you tried to modify a list in a for loop, then only a copy of it could be overwritten, not the original one ( append() is an exception to this). Generally, if you use indexes, you can overwrite the original values.

In my example I used the enumerate() function, which iterates over an iterable (eg a list), and returns an index and the value for it in each iteration. I can use the value to read, and the index to modify it.

In the else clause I completely overwrite the sublist, so I need to put [ and ] to indicate that copy is in a list.

Not very Pythonic, but it works:

og_list = [['a'], ['b'], [], [], ['c'], ['d'], []]

prev = []
for i in range(len(og_list)):
    if len(og_list[i]) == 0:
        og_list[i] = prev
    else:
        prev = og_list[i]

print(og_list)

Result:

[['a'], ['b'], ['b'], ['b'], ['c'], ['d'], ['d']]

Now let's go over your snippet:

copy = 0
for list in ogList:  # cool
    for list in list:  # list in list? would be better to use something like sublist in list to avoid confusion
        for number in list:  # number? what if the inner list stores something that is not a number?
            if number:  # so basically if number is not None or False - why?
                copy = number
                print copy  # print(copy), you forgot the brackets (unless it's Python 2, in which case I have no idea about proper syntax, sorry)
            if not number:  # you could've used an else clause here, a number is or a number is not, these cannot be true at the same time
                list.append(copy)

The problem with your code begins at the for number in list line: this only iterates over elements of a sublist if that sublist itself is not empty - checks you tried executing inside that for loop were therefore useless ( if not number , I assume, was supposed to check if a sublist is empty, but you'd never get here with an empty sublist).

All earlier posts are working pretty well, but it seems that there are some room for improvements.

I find it more naturally to just loop and access directly the original list items w/o using range (and index) or enumerate here. And I'm aware of it take some time for people from other languages...

So here just offer another simpler, maybe more Pythonic approach for your reference:

Note - this program will only work on the assumption that first item in the original list is not empty, as the sample input shown. Since the OP's requirement does not mention that situation.

ogList = [['a'], ['b'], [], [], ['c'], ['d'], []]

out = [ogList[0]]            # initialize to first item

#for i, lst in enumerate(ogList[1:]):   # only if you need idx, item
for lst in ogList[1:]:        # directly access the item, avoid idx
    if not lst:               # empty list encountered
        out.append(out[-1])   # add last item
    else:       
        out.append(lst)       # current lst
        

print(out)          # to confirm the output

# OR this easy way:
expected = [['a'], ['b'], ['b'], ['b'], ['c'], ['d'], ['d']]

assert out == expected          # silence, because they're same

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