如何获取列表中的所有奇数变量?
如果我在Python里创建一个列表,想写一个函数来返回从1到x之间的所有奇数,我该怎么做呢?
比如说,如果我有一个列表[1, 2, 3, 4],这个范围是从1到4(4就是我的x),我想得到的结果是[1, 3]。
3 个回答
如果你想要得到一个范围内的奇数或偶数,直到一个数字 n(可能包括 n 本身),你可以这样做:
def odd_numbers(n):
return range(1, n+1, 2)
def even_numbers(n):
return range(0, n+1, 2)
如果你想要一个通用的方法,从一个序列中提取出奇数 索引 的项,你可以这样做:
import itertools
def odd_indexes(sequence):
return itertools.islice(sequence, 1, None, 2)
def even_indexes(sequence):
return itertools.islice(sequence, 0, None, 2)
下面的代码有什么问题:
def getodds(lst):
return lst[1::2]
....???
(假设你想从某个任意的序列中获取每隔一个的元素,也就是那些索引为奇数的元素)。
另外,如果你想从一个数字列表中获取值为奇数的所有元素,可以这样做:
def oddonly(lst):
return [x for x in lst if x % 2]
[更新:2017]
你可以使用“惰性求值”来从生成器中获取这些元素:
def get_elements_at_odd_indices(sequence):
for index, item in enumerate(sequence):
if index % 2:
yield item
else:
continue
如果你想获取奇数元素(而不是从序列开始的每个奇数位置的元素),可以用更简单的方法:
def get_odd_elements(sequence):
for item in sequence:
if item % 2:
yield item
else:
continue
这适用于任何序列或可迭代对象类型。(显然,后者只适用于那些能产生数字的序列或可迭代对象……或者其他类型能通过% 2得到有意义的“奇数”结果)。
另外,如果我们想高效地操作Pandas系列或数据框的列,或者底层的NumPy,我们可以使用[1::2]切片法来获取奇数索引的元素,而使用NumPy的“花式索引”可以获取每个包含奇数值的元素。
例如:
import numpy as nd
arr = nd.arange(1000)
odds = arr[arr%2!=0]
我把“花式索引”写成arr[arr%2!=0],因为这样可以更好地推广到过滤出每第三个、第四个或其他第n个元素;但你也可以使用更复杂的表达式。
注意,语法arr[arr%2!=0]可能看起来有点奇怪。这是因为NumPy重载了各种算术和位运算符以及增强赋值操作。关键是NumPy会将这些操作转换为机器代码,这样可以高效地在NumPy数组上进行向量化操作……在底层CPU支持的情况下使用SIMD。例如,在今天的典型笔记本和台式机系统上,NumPy可以将许多算术操作转换为SSE操作。
如果你想从一个任意的列表开始:
[item for item in yourlist if item % 2]
但是如果你总是从 range
开始的话,使用 range(1, x, 2)
会更好!-)
举个例子:
$ python -mtimeit -s'x=99' 'filter(lambda(t): t % 2 == 1, range(1, x))'
10000 loops, best of 3: 38.5 usec per loop
$ python -mtimeit -s'x=99' 'range(1, x, 2)'
1000000 loops, best of 3: 1.38 usec per loop
所以在这个情况下,正确的方法比一种比较常见的错误方法快了28倍(!)
这个“比你需要的更通用,但如果这就是你需要的”解决方案:
$ python -mtimeit -s'yourlist=range(1,99)' '[item for item in yourlist if item % 2]'
10000 loops, best of 3: 21.6 usec per loop
速度大约是错误示例的两倍,但仍然比“刚刚好的”方案慢超过15倍!-)