>我正在尝试创建一个元组列表,其中元组内容是列表中9
的数字和它前面的数字。
输入列表:
myList = [1, 8, 9, 2, 4, 9, 6, 7, 9, 8]
期望输出:
sets = [(8, 9), (4, 9), (7, 9)]
法典:
sets = [list(zip(myList[i:i], myList[-1:])) for i in myList if i==9]
当前结果:
[[], [], []]
Cleaner Pythonic 方法:
>>> [(x,y) for x,y in zip(myList, myList[1:]) if y == 9]
[(8, 9), (4, 9), (7, 9)]
上面的代码在做什么:
-
zip(some_list, some_list[1:])
将生成相邻元素对的列表。 - 现在使用该元组,根据第二个元素等于
9
的条件进行过滤。你完了:)
您的部分问题是myList[i:i]
将始终返回一个空列表。切片的末尾是独占的,因此当您执行a_list[0:0]
时,您尝试获取索引 0 和索引 0 之间存在的a_list
元素。
您走在正确的轨道上,但您想将列表本身压缩。
[(x, y) for x, y in zip(myList, myList[1:]) if y==9]
你已经很接近了,如果你刚刚开始,我会告诉你另一种可能更直观的方法:
sets = [(myList[i-1], myList[i]) for i in range(len(myList)) if myList[i] == 9]
获取列表长度范围内的索引,如果位置i
的值等于 9
,则抓取相邻元素。
结果是:
sets
[(8, 9), (4, 9), (7, 9)]
这比其他方法效率低,但我决定取消删除它以向您展示一种不同的方法。您可以通过改用enumerate()
来使其运行得更快一些:
sets = [(myList[i-1], j) for i, j in enumerate(myList) if j == 9]
请注意,在边缘情况下,myList[0] = 9
理解的行为没有zip
和理解的行为是不同的zip
。
具体来说,如果myList = [9, 1, 8, 9, 2, 4, 9, 6, 7, 9, 8]
则:
[(myList[i-1], myList[i]) for i in range(len(myList)) if myList[i] == 9]
# results in: [(8, 9), (8, 9), (4, 9), (7, 9)]
而:
[(x, y) for x, y in zip(myList, myList[1:]) if y==9]
# results in: [(8, 9), (4, 9), (7, 9)]
由您决定哪些符合您的标准,我只是指出它们在所有情况下的行为并不相同。
您也可以通过创建迭代器来执行此操作而无需切片:
l = myList = [1,8,9,2,4,9,6,7,9,8]
it1, it2 = iter(l), iter(l)
# consume first element from it2 -> leaving 8,9,2,4,9,6,7,9,8
next(it2, "")
# then pair up, (1,8), (8,9) ...
print([(i, j) for i,j in zip(it1, it2) if j == 9])
或者使用成对配方创建配对
from itertools import tee, izip
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return izip(a, b)
如果使用python3,只需导入tee并使用常规zip。
没有人添加功能方法,这真的很令人惊讶。
另一个替代答案是使用 filter
.这个内置函数返回一个迭代器(Python2 中的列表),该迭代器由列表中存在的所有元素组成,这些元素返回特定函数的True
>>> myList = [1,8,9,2,4,9,6,7,9,8]
>>> list(filter(lambda x:x[1]==9,zip(myList, myList[1:])))
[(8, 9), (4, 9), (7, 9)]
需要注意的是,只有在python3+中才需要list
调用。本文将详细讨论函数式方法和列表推导之间的区别。
我的解决方案类似于 Jim 的高级零索引检查之一
myList = [9, 1, 8, 9, 2, 4, 9, 6, 7, 9, 8]
[(myList[i-1], x) for i, x in enumerate(myList) if x==9 and i!=0]
# [(8, 9), (4, 9), (7, 9)]