Check if a list contains incrementing elements starting from zero - python

I want to check if a list contains incrementing elements, incremented by one each and starting with 0. So, e.g. [0, 1, 2, 3] should return "valid", whereas e.g. [0, 1, 3, 4] or [-1, 0, 1] should return "not valid".
Is there an easy way to achieve that in Python? Maybe a built-in function?

If the problem is truly as you describe it, this can be solved trivially using range, like so:
myList = [...]
if myList == list(range(myList[-1] + 1)):
# Do stuff.

How about using all :
>>> l = [0, 1, 2, 3]
>>> not l[0] and all(y-x==1 for x,y in zip(l, l[1:]))
True
>>> l1 = [0,1,2,3,5,7]
>>> not l[0] and all(y-x==1 for x,y in zip(l1, l1[1:]))
False
>>> l2 = [0,1,2,3,4,7]
>>> not l[0] and all(y-x==1 for x,y in zip(l2, l2[1:]))
False
>>> l3=[-1,0,1,2]
>>> not l[0] and all(y-x==1 for x,y in zip(l3, l3[1:]))
False
>>> l2 = [0,1,2,3,4,5,7]
>>> not l[0] and all(y-x==1 for x,y in zip(l2, l2[1:]))
False
>>> l4=[0,2,3,4,5,7,8]
>>> not l[0] and all(y-x==1 for x,y in zip(l4, l4[1:]))
False
>>> l5=[0,2,3,4,5,6,7,8]
>>> not l[0] and all(y-x==1 for x,y in zip(l5, l5[1:]))
False
So you can put this into a function, this way:
def check_my_list(lst):
if not lst:
print 'List Empty'
return False
test = not lst[0] and all(y-x==1 for x,y in zip(lst,lst[1:])
return test

I think it can be solved via a one-liner in a functional manner:
print not len(filter(lambda i: i!=-1, [x[i]-x[i+1] for i in range(len(x)-1)]))
given True for x = [0, 1, 2, 3] and False for x = [0, 1, 3, 4]
Explanation:
[x[i]-x[i+1] for i in range(len(x)-1)]
makes a list of differences between successive elements, obviously we want to have all -1...
Then we use filter to select those elements which are different from -1, if there is at least one, it is not a incrementing elements and so the length of such filtered list > 0
If yes, i.e. there are just -1, the field is empty and we get length of 0.

Related

Creating a function that returns an increasing sequence

I am trying to make a function that for a sequence of integers as an array can determine whether it is possible to obtain a strictly increasing sequence by removing no more than one element from the array. If an element can be remove than the output is True otherwise return False. I tried,
def almostIncreasingSequence(sequence):
if sequence[:-1] == sequence[1::]:
return True
else:
return False
It works for list,
sequence = [1, 3, 2, 1]
>>> False
Since you cannot remove any number that would lead to an increasing sequence. However, if the list was
sequence: [1, 3, 2]
>>> True
It is true since you can remove 2 or 3 to have an increasing sequence. My function incorrectly outputs False though.
I really don't see what was your first idea...
How about a more simple solution ?
def fn(seq):
last_i = None
lives = 1
for i in seq :
if last_i is None :
last_i = i
else :
if (i <= last_i):
lives = lives - 1
if (lives < 0) :
return False
last_i = i
return True
>>> fn([1, 3, 2, 1])
False
>>> fn([1, 3, 2])
True
>>> fn([1, 3, 2, 3])
True
>>> fn([1, 3, 2, 4, 6, 8])
True
>>> fn([1, 3, 2, 4, 6, 8, 2])
False
The code below uses the monotonicity check as wrote in this answer and iterates over the elements of the list to check if poping a single element results in increasing monotonicity.
def strictly_increasing(L):
return all(x<y for x, y in zip(L, L[1:]))
def non_decreasing(L):
return all(x<=y for x, y in zip(L, L[1:]))
L = [1, 3, 2]
L_mod = L.copy()
my_bool = False
if not strictly_increasing(L):
for i, x in enumerate(L):
L_mod.pop(i)
if strictly_increasing(L_mod):
my_bool = True
exit
else: L_mod = L.copy()
else:
my_bool = True
Use strictly_increasing or non_decreasing as you wish.

Python: List Equal List or For each in list Append

Would it be OK to use an '=' equal sign while working with the lists? The code below results to a consistent behavior of myOtherList even after myList has been changed. Is there any hidden benefit of using .append() instead of '=' straight equal sign?
myList=[1, 2, 3, 4, 5]
myOtherList=myList
myThirdList=[]
for each in myList:
myThirdList.append(each)
print myOtherList==myThirdList # True
myList=[]
print myOtherList==myThirdList # True
There's a very significant difference between == and is
Given your example:
>>> myList = [1, 2, 3, 4, 5]
>>> myOtherList = myList
>>> myOtherList == myList
True
>>> myOtherList is myList
True
That indicates that not only do the two lists contain the same values in the same order, they are in fact, the same list. Whereas:
>>> myThirdList = []
>>> for each in myList:
myThirdList.append(each)
>>> myList == myThirdList
True
>>> myList is myThirdList
False
They are now two different lists that contain the same values, in the same order.

Remove evens from a list with del function

I'm not allowed to use the .remove() function to delete even numbers in a list and the specs say: You will be modifying the original list, so its id() must not change.This is what I have:
def remove_evens(xs):
for i in range(len(xs)):
for x in xs:
if x%2==0:
del xs[i]
return xs
If for instance I test the function and I input xs=[1,2,3,4,5] it returns [3,5]. I don't know why the 1 doesn't return
That's because you're iterating over the list and modifying it at the same time. This means the index i isn't always correct because you've just removed an element from the list. This leads to skipping elements and that's why the 1 isn't in there.
You can do:
def remove_evens(xs):
return [x for x in xs if x % 2 != 0]
This uses a list comprehension to create a list without the even numbers. If you need to modify the existing list you can do:
def remove_evens(xs):
to_remove = []
for i, x in enumerate(xs):
if x % 2 == 0:
to_remove.append(i)
for j in to_remove:
del xs[j]
return xs
This creates a list to_remove which keeps track of the positions of the elements that need to be removed.
Maybe something like this will work for you.
>>> xs = [1,5,123,6,2,34]
>>> id(xs)
35519496L
>>> lastidx = len(xs) - 1
>>> for i, x in enumerate(reversed(xs)):
... if x%2==0:
... del xs[lastidx-i]
...
>>> xs
[1, 5, 123]
>>> id(xs)
35519496L
It's linear time because it iterates over the list only once. When you iterate over a list backwards, you can freely delete elements without modifying the indexes of future elements that you haven't looped over yet. Also the id of the list does not change with this method, as you can see. :)
Here is another way to do the same thing with only range/xrange and len.
>>> xs = [1,5,123,6,2,34]
>>> for i in range(len(xs)-1,-1,-1):
... if xs[i]%2==0:
... del xs[i]
...
>>> xs
[1, 5, 123]
Both ways do the same thing so whichever way you decide to use is a matter of preference/personal style.
It’s a bad idea to delete items from a list as you are iterating over the list.
Here’s a few ways in which you can achieve your goal:
>>> def deleteEvens(L):
... dels = []
... for i,x in enumerate(L):
... if not x%2:
... dels.append(i)
... for d in dels[::-1]:
... L.pop(d)
...
>>> L
[1, 2, 3, 4, 5]
>>> deleteEvens(L)
>>> L
[1, 3, 5]
OR
>>> L = [1,2,3,4,5]
>>> odds = [i for i in L if i%2]
>>> odds
[1, 3, 5]
OR
>>> def delEvens(L):
... dels = []
... for i,x in enumerate(L):
... if not x%2:
... dels.append(i)
... for d in dels[::-1]:
... del L[d]
...
>>> L = [1,2,3,4,5]
>>> delEvens(L)
>>> L
[1, 3, 5]

return a list containing elements of another list

I need to write an expression and I'm completely stuck. I have part of the code that I think I have written correctly but I'm stick on the rest of it. I need the code to return a new list containing every 3rd element in the list, starting at index 0.
For example: if I have the list [0, 1, 2, 3, 4, 5] I need it to return [0, 3]
The code I have so far is:
result = []
i = 0
while i < len(L):
result.append(L[i])
i =
return result
Can someone please help me figure out what I need the i = expression to be for this code to work.
First of all, you can make use of extended slice notation to make things easier:
In [1]: l = [0, 1, 2, 3, 4, 5]
In [2]: l[::3]
Out[2]: [0, 3]
From the docs:
Some sequences also support “extended slicing” with a third “step” parameter: a[i:j:k] selects all items of a with index x where x = i + n*k, n >= 0 and i <= x < j.
As for your code sample, you probably need i = i + 3 or i += 3 there.
Maybe try this:
result = []
for i in range(0, len(L), 3):
result.append(L[i])
return result
Another alternative is to use enumerate.
[j for i, j in enumerate([0, 1, 2, 3, 4, 5]) if i % 3 == 0]
this will give tyou an iterable sequence:
import itertools
l = [0, 1, 2, 3, 4, 5]
itertools.islice(l, 0, None, 3)
to turn it into a list, use the list() function.
impiort itertools
def get_sublist(l):
return list(itertools.islice(l, 0, None, 3))
python 3.2
one way:
>>> [i for i in range(0,len(L),3)]
[0,3]
your method:
result = []
i = 0
while i <= len(L):
result.append(L[i])
i+=3
return result

How can I compare the values of two lists in python?

I want to compare the values of two lists.
For example:
a = [1, 2, 3]
b = [1, 2, 3]
I need to check if a is same as b or not. How do I do that?
a == b
This is a very simple test, it checks if all the values are equal.
If you want to check if a and b both reference the same list, you can use is.
>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> a is b # a and b have the same values but refer to different lists in memory
False
>>> a = [1, 2, 3]
>>> b = a
>>> a is b # both refer to the same list
True
simply use
a == b
the operator == will compare the value of a and b, no matter whether they refer to the same object.
#jamylak's answer is what I would go with. But if you're looking for "several options", here's a bunch:
>>> a = [1,2,3]
>>> b = [1,2,3]
>>> a == b
True
OR
def check(a,b):
if len(a) != len(b):
return False
for i in xrange(len(a)):
if a[i] != b[i]:
return False
return True
OR
>>> len(a)==len(b) and all((a[i]==b[i] for i in xrange(len(a))))
True
OR
def check(a,b):
if len(a) != len(b):
return False
for i,j in itertools.izip(a,b):
if i != j:
return False
return True
OR
>>> all((i==j for i,j in itertools.izip(a,b)))
True
OR (if the list is made up of just numbers)
>>> all((i is j for i,j in itertools.izip(a,b)))
True
OR
>>> all((i is j for i,j in itertools.izip(a,b)))
True
Hope that satiates your appetite ;]

Categories