Remove adjacent element in a list in python - python-2.7

I am trying to do a simple python program that removes all the adjacent elements in a list
def main():
a = [1, 5, 2, 3, 3, 1, 2, 3, 5, 6]
c = len(a)
for i in range (0, c-2):
if a[i] == a[i+1]:
del a[i]
c = len(a)
print a
if __name__ == '__main__':
main()
and the output is
[1, 5, 2, 3, 3, 2, 3, 5, 6] which is all fine!
If change the a list to a = [1, 5, 2, 3, 3, 1, 2, 2, 5, 6]
then it gives an error
index list out of range
**if a[i] == a[i+1]**
It shouldn't be complaining about the index out of range as I am calculating the len(a) every time it deletes an element in the list. What am I missing here?

for i in range (0, c-2):
This is not like a for loop in some other languages; it’s iterating over a list returned (once) by range. When you change c later, it does not affect this loop.
You can use while instead:
c = len(a)
while i < c - 2:
if a[i] == a[i + 1]:
del a[i]
c = len(a)
else:
i += 1
There’s also itertools.groupby:
import itertools
def remove_consecutive(l):
return (k for k, v in itertools.groupby(l))

Here's a slightly different approach:
origlist=[1, 5, 2, 3, 3, 1, 2, 3, 5, 6]
newlist=[origlist[0]]
for elem in origlist[1:]:
if (elem != newlist[-1]):
newlist.append(elem)
The itertools answer above may be preferred, though, for brevity and clarity...

Related

Eigen MatrixXi to VectorXi conversion

I have a MatrixXi, say
[0, 1, 2]
[0, 2, 3]
[4, 7, 6]
[4, 6, 5]
[0, 4, 5]
[0, 5, 1]
[1, 5, 6]
I get a part of it by doing:
MatrixXi MR = F.middleRows(first, last);
with first and last at will. Now I'd like to turn those n rows into a column VectorXi, like:
[0,
1,
2,
0,
2,
3]
possibly without using a for loop. I've tried:
VectorXi VRT(MR.rows() * MR.cols());
VRT.tail(MR.rows() * MR.cols()) = MR.array();
But I get:
Assertion failed: (rows == this->rows() && cols == this->cols() && "DenseBase::resize() does not actually allow to resize."), function resize, file /Users/max/Developer/Stage/Workspace/AutoTools3D/dep/libigl/external/eigen/Eigen/src/Core/DenseBase.h, line 257.
How do I get that? I'm using Eigen before v4 so I cannot use reshape...
Thank you
As pointed out by chtz, this works:
Eigen::VectorXi VR(MR.size());
Eigen::MatrixXi::Map(VR.data(), MR.cols(), MR.rows()) =
MR.transpose();

Using index reference in a for loop iterations [duplicate]

Here is a snippet of code which gives the output: 0 1 2 2. I had expected the output 3 3 3 3 since a[-1] accesses the number 3 in the list. The explanation given online says "The value of a[-1] changes in each iteration" but I don't quite understand how or why. Any explanations would be great!
a = [0, 1, 2, 3]
for a[-1] in a:
print(a[-1])
While doing for a[-1] in a, you actually iterate through the list and temporary store the value of the current element into a[-1].
You can see the loop like these instructions:
a[-1] = a[0] # a = [0, 1, 2, 0]
print(a[-1]) # 0
a[-1] = a[1] # a = [0, 1, 2, 1]
print(a[-1]) # 1
a[-1] = a[2] # a = [0, 1, 2, 2]
print(a[-1]) # 2
a[-1] = a[3] # a = [0, 1, 2, 2]
print(a[-1]) # 2
So, when you are on the third element, then 2 is stored to a[-1] (which value is 1, but was 0 before and 3 on start).
Finally, when it comes to the last element (and the end of the iteration), the last value stored into a[-1] is 2 which explains why it is printed twice.
What's happening here is a list is mutated during looping.
Let's consider following code snippet:
a = [0, 1, 2, 3]
for a[-1] in a:
print a
Output is:
[0, 1, 2, 0]
[0, 1, 2, 1]
[0, 1, 2, 2]
[0, 1, 2, 2]
Each iteration:
reads value from position currently pointed by internal pointer
immediately assigns it to last element in list
after that last element is printed on standard output
So it goes like:
internal pointer points to first element, it's 0, and last element is overwritten with that value; list is [0, 1, 2, 0]; printed value is 0
internal pointer points to second element, it's 1, and last element is overwritten with that value; list is [0, 1, 2, 1]; printed value is 1
(...)
at last step, internal pointer points to last element; last element is overwritten by itself - list does not change on last iteration; printed element also does not change.
This code
a = [0, 1, 2, 3]
for a[-1] in a:
print(a[-1])
is equivalent to
a = [0, 1, 2, 3]
for i in range( len(a) ):
a[-1] = a[i] # update last element of list(updated) with element at i'th position
print(a[-1]) # print last element of list
the output will be 0 1 2 2
Explanation:
len(a) = 4, range( len(a) ) = [0, 1, 2, 3]
1st loop, current list = [0, 1, 2, 3], i = 0 => a[i] = a[0] = 0, updated list = [0, 1, 2, 0], last element a[-1] = 0
2nd loop, current list = [0, 1, 2, 0], i = 1 => a[i] = a[1] = 1, updated list = [0, 1, 2, 1], last element a[-1] = 1
3rd loop, current list = [0, 1, 2, 1], i = 2 => a[i] = a[2] = 2, updated list = [0, 1, 2, 2], last element a[-1] = 2
4th loop, current list = [0, 1, 2, 2], i = 3 => a[i] = a[3] = 2, updated list = [0, 1, 2, 2], last element a[-1] = 2

Find index of item in list where sum of start of list to index is greater than X

I am looking for a fast implementation of the following code; using, for instance, map() or next():
l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
total_so_far = 0
for i in l:
total_so_far += i
if total_so_far > 14:
break
print(i)
The code prints the index of item in list where sum of start of list to the index is greater greater than 14.
Note: I need to continuously update the link in another loop. Therefore, a solution in numpy would probably be too slow, because it cannot update a list in-place.
You can also make use of itertools.accumulate() together with enumerate() and next():
In [1]: from itertools import takewhile
In [2]: l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [3]: next(index for index, value in enumerate(accumulate(l)) if value > 14)
Out[3]: 5

How to switch values in a list to print an alternated version of the list?

I'm having some trouble figuring out how to switch numbers in a long list.
For example if were to have a list:
numbers = [1,2,3,4,5,6,7,8]
and wanted to instead print it in the form of:
numbers_2 = [2,1,4,3,6,5,8,7]
such that each pair would be switched, using a for-loop. I thought about doing something like:
for i in range(0, len(numbers), 2):
But wasn't really able to get much further.
Loop every second index and swap two adjacent items:
numbers = [1,2,3,4,5,6,7,8]
for i in range(1, len(numbers), 2):
numbers[i-1], numbers[i] = numbers[i], numbers[i-1]
Not sure about the other answers, but this one will also work with a list of an uneven length, and leave the last item untouched.
Take 2 halves, and rearrange them:
numbers = [1,2,3,4,5,6,7,8]
first = numbers[::2]
second = numbers[1::2]
numbers_2 = sum(map(list, zip(second, first)), [])
Try this:
def swap_array_elements (a):
for i in range (0, len(a) - 1, 2):
a[i], a[i +1] = a[i + 1], a[i]
return a
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print (swap_array_elements (a))
# prints: [1, 0, 3, 2, 5, 4, 7, 6, 9, 8]

finding how many times a sequence repeats in a data frame using python

Is there a way to find how many times a sequence repeats in a dataframe?
Lets say I have a dataframe with a large number of 1 and 3's and I wanted to see how much this sequence [3,1,3,3,1] repeats.
here's an example list. 3,1,3,3,1,3,3,1,3,3,1,3,1,1,1,1,3,1,3,1,1,3,3,3
Here's an example of what I'm trying to do
this first part would be true 3,1,3,3,1,3,3,1,3,3,1,3,1,1,1,1,3,1,3,1,1,3,3,3
this second part would be false 3,1,3,3,1,3,3,1,3,3,1,3,1,1,1,1,3,1,3,1,1,3,3,3
and the third part would be false
3,1,3,3,1,3,3,1,3,3,1,3,1,1,1,1,3,1,3,1,1,3,3,3
I want to analyze sections at a time according to the length of the sequence I'm trying to find. In numeric order of the data frame.
My data Is in a dateandtime format. But I can change that.
Thanks for all your help I really appreciate it everything everybody does on this site.
my_list = np.array([3, 1, 3, 3, 1, 3, 3, 1, 3, 3, 1, 3, 1, 1, 1, 1, 3, 1, 3, 1, 1, 3, 3, 3])
target = np.array([3, 1, 3, 3, 1])
(my_list.reshape(-1, len(sequence)) == sequence[None, :]).all(axis=1)
This converts a list of numbers into a comma separated string, and then compares each sequential chunk to the target.
from itertools import izip_longest
my_list = [3, 1, 3, 3, 1, 3, 3, 1, 3, 3, 1, 3, 1, 1, 1, 1, 3, 1, 3, 1, 1, 3, 3, 3]
target = [3, 1, 3, 3, 1]
n = len(target)
>>> sum(all(a == b for a, b in izip_longest(target, my_list[(i * n):((i + 1) * n)]))
for i in range(len(my_list) // n))
1
Below is an alternative method that converts the integers to strings and then compares the strings.
target = ",".join(str(number) for number in target)
>>> target
'3,1,3,3,1'
>>> sum(",".join(str(number) for number in my_list[(i * n):(i * n + n)]) == target
for i in range(len(my_list) / n))
1
To give some more intuition on what is going on, the list is chunked five elements at a time and then those elements are joined as a string. These strings are then compared to the target string which was similarly converted, and the number of matches are then summed.
>>> [",".join(str(number) for number in my_list[(i * n):(i * n + n)])
for i in range(len(my_list) / n)]
['3,1,3,3,1', '3,3,1,3,3', '1,3,1,1,1', '1,3,1,3,1']
Step1
Convert list of integers into string.
Step2
Use findall() function of regex module to find all occurences of target_string in my_list_string.
import re
my_list = [3, 1, 3, 3, 1, 3, 3, 1, 3, 3, 1, 3, 1, 1, 1, 1, 3, 1, 3, 1, 1, 3, 3, 3]
target = [3, 1, 3, 3, 1]
my_list_string = ''.join(str(e) for e in my_list)
target_string = ''.join(str(e) for e in target)
print(len(re.findall(target_string, my_list_string)))