Here is a list where I would like to keep only the 'windows' where there are a group of number higher than 3, but if in any case inside this group you find a smaller number, you keep it.
Moreover, if there is an isolated high number (between zeros for example), we need to delete it.
l = [3.5, 0, 0, 0.5, 4, 10, 20, 3, 20, 10, 2, 0, 0, 3.5, 0, 2, 18, 15, 2, 14, 2, 0]
and the expected result :
[4, 10, 20, 3, 20, 10, 18, 15, 2, 14]
This program does it but I feel this it not very pythonic, could you think of any other way ?
l = [3.5, 0, 0, 0.5, 4, 10, 20, 3, 20, 10, 2, 0, 0, 3.5, 0, 2, 18, 15, 2, 14, 2, 0]
new_l = []
index = []
seuil = 3
for i, elt in enumerate(l):
if elt > seuil:
if (l[i-1] and l[i+1]) > 1:
new_l.append(elt)
index.append(i)
else:
pass
else:
try:
if (l[i-1] and l[i+1]) > seuil:
new_l.append(elt)
index.append(i)
except IndexError:
pass
print index
print new_l
1 Answer 1
- Write functions, improvements can range from faster code to the ability to reliably time or profile your code.
- You don't need to use
else
if you're just usingpass
in that block. - Your code is WET, so it's not DRY. Instead of duplicating the code, you could instead assign to a variable in the
if
andelse
, to check against. - You may want to get into a habit of using
if __name__ == '__main__':
. In short, if you import the file it won't run the code.
This can get you:
def rename_me(l, seuil):
new_l = []
index = []
for i, elt in enumerate(l):
bound = 1 if elt > seuil else seuil
try:
if (l[i-1] and l[i+1]) > bound:
new_l.append(elt)
index.append(i)
except IndexError:
pass
return index, new_l
A couple more things:
- I think you have a bug,
(l[i-1] and l[i+1]) > bound
probably isn't doing what you think it is. It's only checking ifl[i+1]
is greater thanbound
. As1 and 2 == 2
and0 and 2 == 0
are both true. Instead you may want to usel[i-1] > bound < l[i+1]
. - I don't see why you'd need the indexes and the elements from the original list, and so you could instead just return one or the other.
- You can change the function to be a generator function, as this reduces memory usage.
- You could use a modified
itertools.pairwise
, to remove theIndexError
.
from itertools import tee
def rename_me(l, seuil):
a, b, c = tee(l, 3)
next(b, None)
next(c, None)
next(c, None)
for index, (i, j, k) in enumerate(zip(a, b, c), 1):
if i > (1 if j > seuil else seuil) < k:
yield index
-
\$\begingroup\$ Ok thanks a lot. One question : what do you call a generator function ? \$\endgroup\$Natha– Natha2017年01月06日 19:16:06 +00:00Commented Jan 6, 2017 at 19:16
-
\$\begingroup\$ @Annabelle I assume you mean how do you call it, to get a list from it you can do
list(rename_me(l, seuil))
, but it's almost the same asrange
in Python 3 orxrange
in Python 2 \$\endgroup\$2017年01月06日 19:18:50 +00:00Commented Jan 6, 2017 at 19:18
index
list? It is not used in the code itself. \$\endgroup\$index
list only actually. Thenew_l
is only to check if the process goes well. \$\endgroup\$