for i in range(15):
print i #will print out 0..14
for i in range(1, 15):
print i # will print out 1..14
for i in range (a, b, s):
print i # will print a..b-1 counting by s. interestingly if while counting by the step 's' you exceed b, it will stop at the last 'reachable' number, example
for i in range(1, 10, 3):
print i
> 1
> 4
> 7
List Splicing:
a = "hello" # there are 5 characters, so the characters are accessible on indexes 0..4
a[1] = 'e'
a[1:2] = 'e' # because the number after the colon is not reached.
a[x:y] = all characters starting from the character AT index 'x' and ending at the character which is before 'y'
a[x:] = all characters starting from x and to the end of the string
In the future, if you ever wonder what the behavior of python is like, you can try it out in the python shell. just type python in the terminal and you can enter any lines you want (though this is mostly convenient for one-liners rather than scripts).
Answer from Jeremy Fisher on Stack Overflowfor i in range(15):
print i #will print out 0..14
for i in range(1, 15):
print i # will print out 1..14
for i in range (a, b, s):
print i # will print a..b-1 counting by s. interestingly if while counting by the step 's' you exceed b, it will stop at the last 'reachable' number, example
for i in range(1, 10, 3):
print i
> 1
> 4
> 7
List Splicing:
a = "hello" # there are 5 characters, so the characters are accessible on indexes 0..4
a[1] = 'e'
a[1:2] = 'e' # because the number after the colon is not reached.
a[x:y] = all characters starting from the character AT index 'x' and ending at the character which is before 'y'
a[x:] = all characters starting from x and to the end of the string
In the future, if you ever wonder what the behavior of python is like, you can try it out in the python shell. just type python in the terminal and you can enter any lines you want (though this is mostly convenient for one-liners rather than scripts).
The best way to clarify such doubts is to play with the REPL:
>>> range(10)
range(0, 10)
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x = list(range(10))
>>> x[:3]
[0, 1, 2]
>>> x[:1]
[0]
>>> x[1:10]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Videos
a = [12,11,5,7,2,21,32,13,6,42,1,8,9,0,32,38]
indices = [idx for idx,val in enumerate(a) if val < 10]
This creates a list of indices:
[2, 3, 4, 8, 10, 11, 12, 13]
I would recommend keeping it that way for easy parsing, but you can also turn it into ranges as follows:
ranges = [[]]
for val in indices:
if not ranges[-1] or ranges[-1][-1] == val-1:
ranges[-1].append(val)
else:
ranges.append([val])
This creates a list of ranges:
[[2, 3, 4], [8], [10, 11, 12, 13]]
Now to take out the middle:
ranges = [[item[0],item[-1]] if len(item) > 1 else item for item in ranges]
Result:
[[2, 4], [8], [10, 13]]
You can have your function take a function as an argument to use as the predicate for building your intervals:
def indexscope(dlist, predicate):
scope = []
start = end = -1
for i, v in enumerate(dlist):
if predicate(v):
if start == -1:
start = end = i
continue
if end + 1 == i:
end = i
else:
scope.append([start] if start == end else [start, end])
start = end = i
if start != -1:
scope.append([start] if start == end else [start, end])
return scope
a = [12,11,5,7,2,21,32,13,6,42,1,8,9,0,32,38]
def less_than_10(n):
return n < 10
print(indexscope(a, less_than_10))
print(indexscope(a, lambda x: x > 20))
[[2, 4], [8], [10, 13]]
[[5, 6], [9], [14, 15]]
with scipy:
import numpy as np
import scipy.ndimage as nd
def passing_ranges(a, predicate):
return nd.find_objects(nd.label(predicate(a))[0])
The results are returned as slice objects, but that is to your advantage because you can use them to against your original np array:
small_a = [12,11,5,7,2,21,32,13,6,42,1,8,9,0,32,38]
small_np_array = np.array(small_a)
valid_ranges = passing_ranges(small_np_array, lambda n: n < 10)
for r in valid_ranges:
print(r[0], small_np_array[r])
slice(2, 5, None) [5 7 2]
slice(8, 9, None) [6]
slice(10, 14, None) [1 8 9 0]
benchmarks
large_a = [12,11,5,7,2,21,32,13,6,42,1,8,9,0,32,38]*1000000
large_np_array = np.array(large_a)
%timeit passing_ranges(large_np_array, lambda x: x < 10)
1 loops, best of 3: 1.2 s per loop
%timeit indexscope(large_a, lambda n: n < 10)
1 loops, best of 3: 6.99 s per loop
Here is your answer, I even inline the predicate to remove a function call:
from itertools import groupby, count
def xibinke(a):
l = [idx for idx,value in enumerate(a) if value<10]
return [list(g) for _,g in groupby(l,key=lambda n,c=count():n-next(c))]
%timeit xibinke(large_a)
1 loops, best of 3: 14.6 s per loop
If you really want to use manual indexing, then dont use enumerate() and just create a range() (or xrange() if Python 2.x) of the right size, ie:
for i in xrange(len(a) - 2):
# code here
Now you don't have to manually take care of indexes at all - if you want to iterate over (a[x], a[x+1]) pairs all you need is zip():
for x, y in zip(a, a[1:]):
if abs(x - y) < min:
min = abs(x - y)
zip(seq1, seq2) will build a list of (seq1[i], seq2[i]) tuples (stopping when the smallest sequence or iterator is exhausted). Using a[1:] as the second sequence, we will have a list of (a[i], a[i+1]) tuples. Then we use tuple unpacking to assign each of the tuple's values to x and y.
But you can also just use the builtin min(iterable) function instead:
min(abs(x - y) for x, y in zip(a, a[1:]))
which is the pythonic way to get the smallest value of any sequence or iterable.
Note that with Python 2.x, if your real list is actually way bigger, you'll benefit from using itertools.izip instead of zip
As as side note, using min (actually using any builtin name) as a variable name is possibly not a good idea as it shadows the builtin in the current namespace. If you get a TypeError: 'int' object is not callable message trying this code you'll know why...
You can pass a slice of a with the specified start and stop indices to enumerate:
for i, x in enumerate(a[:size-1]):
...
i will run from 0 to size-2
On a side note, comments in Python start with # and not //
You can achieve the same results by using min on a generator expression created from the zip of a and its advanced slice:
minimum = min(abs(i - j) for i, j in zip(a, a[1:]))
Also, be careful to not use the name min as this already shadows the builtin min. Something you obviously don't want.
Numpy slicing allows you to input a list of indices to an array so that you can slice to the exact values you want.
For example:
import numpy as np
a = np.random.randn(10)
a[[2,4,6,8]]
This will return the 2nd, 4th, 6th, and 8th array elements (keeping in mind that python indices start from 0). So, if you want every 2nd element starting from an index x, you can simply populate a list with those elements and then feed that list into the array to get the elements you want, e.g:
idx = list(range(2,10,2))
a[idx]
This again returns the desired elements (index 2,4,6,8).
Your x is an array of length 20
x = np.arange(0,20)
Returns
x [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
Access every nth(even indices here) element ignoring first two and last two indices in the array x by
print(x[2:len(x)-1:2])
Returns
[2 4 6 8]
And for the rest in similar fashion,
print(x[5:len(x)-1:5])
print(x[4:len(x)-1:4])
Returns
[ 5 10 15]
[ 4 8 12 16]
One alternative is to do:
mylist1 = [11, 4, 5, 6, 8, 6, 3]
for i in mylist1:
a = list(range(i))
print(a[-2:] + a[:2])
Output
[9, 10, 0, 1]
[2, 3, 0, 1]
[3, 4, 0, 1]
[4, 5, 0, 1]
[6, 7, 0, 1]
[4, 5, 0, 1]
[1, 2, 0, 1]
You could try something like this:
list1 = [0, 1, 2, 3, 4, 5]
for ln in range(1, len(list1)):
list2 = [list1[n] for n in range(-ln, ln)] #magic line
print(list2)
or you could also try this instead of the magic line:
list2 = list1[ln:] + list1[:ln]
Where ln is the number of elements you want from the end and the beginning of the list.
Are there circumstances where for i in range(len(my_list)): is to be preferred over for i, _ in enumerate(my_list):? If so, what are they, generally speaking?
Edited to fix syntax.