Removing Dicts with Null values from Only the End of a List Given input such as:


foos = [
    [],
    [{'a': 1}],
    [{'a': 1}, {'a': 2}],
    [{'a': 1}, {'a': 2}, {'a': None}],
    [{'a': 1}, {'a': 2}, {'a': None}, {'a': None}],
    [{'a': 1}, {'a': None}, {'a': 2}],
    [{'a': 1}, {'a': None}, {'a': 2},  {'a': None}],
    [{'a': 1}, {'a': None}, {'a': 2},  {'a': None}, {'a': None}],
]


I want a function remove_empty_end_lines that takes a list of dicts and will remove all dicts with null values that only appear at the end of the list, not in between.


for foo in foos:
    print(foo)
    print(remove_empty_end_lines(foo))
    print('\n')

[]
[]

[{'a': 1}]
[{'a': 1}]

[{'a': 1}, {'a': 2}]
[{'a': 1}, {'a': 2}]

[{'a': 1}, {'a': 2}, {'a': None}]
[{'a': 1}, {'a': 2}]

[{'a': 1}, {'a': 2}, {'a': None}, {'a': None}]
[{'a': 1}, {'a': 2}]

[{'a': 1}, {'a': None}, {'a': 2}]
[{'a': 1}, {'a': None}, {'a': 2}]

[{'a': 1}, {'a': None}, {'a': 2}, {'a': None}]
[{'a': 1}, {'a': None}, {'a': 2}]

[{'a': 1}, {'a': None}, {'a': 2}, {'a': None}, {'a': None}]
[{'a': 1}, {'a': None}, {'a': 2}]



My final solution is:

def remove_empty_end_lines(lst):
    i = next(
        (
            i for i, dct in enumerate(reversed(lst))
            if any(v is not None for v in dct.values())
         ),
        len(lst)
    )

    return lst[: len(lst) - i]


I'm not going for code golf, rather for performance and readability.

In the input I've listed above, the dicts are always a length of one, butin reality the lengths can be any amount. The lengths of each dict within a list will always be the same.
Some suggestions:


You are using i both inside your list comprehension and outside. This makes the code harder to follow than if the variables were differently named. For example, you could think of the outer i as the count of matching (that is, all None values) dictionaries at the end of the list.
Hungarian notation abbreviations like lst and dct don't tell me anything about what the variables actually are. In an actual application this should be possible, but more context would be needed for that.
You say "remove all dicts with null values", but you neither specify nor test what happens with a dictionary having some None values and some non-None values at the end of the list. As far as I can tell from your implementation you remove only entries with all None values, but it's not clear whether this is the intention.
I would pull out the tuple passed to next as a separate variable for clarity.