I'm looking for a way to easily determine if all not None items in a list occur in a single continuous slice. I'll use integers as examples of not None items.
For example, the list [None, None, 1, 2, 3, None, None]
meets my requirements for continuous integer entries. By contrast, [1, 2, None, None, 3, None]
is not continuous, because there are None entries between integers.
Some more examples to make this a clear as possible.
Continuous:
[1, 2, 3, None, None]
[None, None, 1, 2, 3]
[None, 1, 2, 3, None]
Not Continuous:
[None, 1, None, 2, None, 3]
[None, None, 1, None, 2, 3]
[1, 2, None, 3, None, None]
My first approach was to use variables to keep track of whether or not we had come across a None
yet, and whether or not we had come across an int
yet -- this ends up with a highly nested and very difficult to follow series of if/else statements embedded in a for loop. (On top of the ugliness, I confess I haven't gotten it to work in every case).
Anyone know an easier way to figure out if the not None items in a list occur in a single continuous slice?
This may not be the best way to go about doing it, but you can look for the first non-None entry and the last
non-None
entry and then check the slice forNone
. e.g.:This will work for any sequence type.
This algorithm does the work with a few drawbacks (it removes items form the list). But it's a solution.
Basically if you remove all continuous
None
from start and the end. And if you found someNone
in the list then the integers are not in a continuous form.Yet, another example of how small code could become evil.
I wish a
strip()
method were available forlist
.Here are a couple of examples. You can use
next(seq)
to get the next item from an iterator. I'll put a mark pointing to the next item after eachexample1:
example2:
One liner:
The real work is done by the
strip
function. If there are spaces in a stripped string, then they're not leading/trailing. The rest of the function converts the list to a string, which has a space for eachNone
.No! Actually you need only one variable. Thinking this problem in the view of Finite State Machine(FSM) with your approach will lead to a quite nice solution.
We call the state
p
. At first,p
is 0. Then we start walking between the states.When all the elements in the list is examinated and still don't fail then the answer is
True
.One version that encode the translation table in a dict
Another version that use if statement:
So my point is that using
if
andfor
are still pythonic.update
I found another way to encode the FSM. We can pack the translation table into a 12bit integer.
Here 3684, the magic number, can be obtained by:
The readability is not as good as other version but it's faster since it avoids dictionary lookup. The second version is as fast as this but this encoding idea can be generalized to solve more problems.
You could use something like
itertools.groupby
:This will iterate only until it sees a group twice. I'm not sure if you consider
[None, None]
, so tweak it to your needs.