python和其他一些(功能)编程语言的主要优势之一是list comprehension。它们允许程序员在一行中编写复杂的表达式。它们最初可能会令人困惑,但如果习惯了语法,那么它比嵌套复杂的循环要好得多。
话虽如此,请与我分享一些列表理解的最酷用法。 (通过酷,我只是说有用)它可能是一些编程竞赛,或生产系统。
例如:
要进行矩阵mat
>>> mat = [
... [1, 2, 3],
... [4, 5, 6],
... [7, 8, 9],
... ]
>>> [[row[i] for row in mat] for i in [0, 1, 2]]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
请提供表达式的说明及其使用位置(如果可能)。
答案 0 :(得分:16)
很多人不知道Python允许您使用if
过滤列表推导的结果:
>>> [i for i in range(10) if i % 2 == 0]
[0, 2, 4, 6, 8]
答案 1 :(得分:9)
我经常使用理解来构建dicts:
my_dict = dict((k, some_func(k)) for k in input_list)
注意Python 3具有字典理解,因此它变为:
my_dict = {k:some_func(k) for k in input_list}
用于从元组列表构建类似CSV的数据:
data = "\n".join(",".join(x) for x in input)
实际上并不是列表理解,但仍然有用:从“切割点”列表中生成范围列表:
ranges = zip(cuts, cuts[1:])
答案 2 :(得分:8)
要进行矩阵mat
的转置:
>>> [list(row) for row in zip(*mat)]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
答案 3 :(得分:8)
要展平列表清单:
>>> matrix = [[1,2,3], [4,5,6]]
>>> [x for row in matrix for x in row]
[1, 2, 3, 4, 5, 6]
答案 4 :(得分:7)
如果“酷”意味着疯狂,我喜欢这个:
def cointoss(n,t):
return (lambda a:"\n".join(str(i)+":\t"+"*"*a.count(i) for i in range(min(a),max(a)+1)))([sum(randint(0,1) for _ in range(n)) for __ in range(t)])
>>> print cointoss(20,100)
3: **
4: ***
5: **
6: *****
7: *******
8: *********
9: *********
10: ********************
11: *****************
12: *********
13: *****
14: *********
15: *
16: **
n和t控制每次测试的硬币抛出次数以及测试运行的次数和绘制分布。
答案 5 :(得分:4)
我在使用以井号标记开头的可选注释行加载制表符分隔文件时始终使用此功能:
data = [line.strip().split("\t") for line in open("my_file.tab") \
if not line.startswith('#')]
当然它也适用于任何其他评论和分隔符。
答案 6 :(得分:3)
我目前有几个脚本需要按高度将一组点分组为“级别”。假设点的z值将围绕对应于水平的某些值松散地聚集,在簇之间存在大的间隙。
所以我有以下功能:
def level_boundaries(zvalues, threshold=10.0):
'''Finds all elements z of zvalues such that no other element
w of zvalues satisfies z <= w < z+threshold.'''
zvals = zvalues[:]
zvals.sort()
return [zvals[i] for i, (a, b) in enumerate(pairs(zvals)) if b-a >= threshold]
“pair”直接来自itertools模块文档,但仅供参考:
def pairs(iterable):
'iterable -> (iterable[n], iterable[n+1]) for n=0, 1, 2, ...'
from itertools import izip, tee
first, second = tee(iterable)
second.next()
return izip(first, second)
一个人为的用法示例(我的实际数据集太大而无法用作示例):
>>> import random
>>> z_vals = [100 + random.uniform(-1.5,1.5) for n in range(10)]
>>> z_vals += [120 + random.uniform(-1.5,1.5) for n in range(10)]
>>> z_vals += [140 + random.uniform(-1.5,1.5) for n in range(10)]
>>> random.shuffle(z_vals)
>>> z_vals
[141.33225473458657, 121.1713952666894, 119.40476193163271, 121.09926601186737, 119.63057973814858, 100.09095882968982, 99.226542624083109, 98.845285642062763, 120.90864911044898, 118.65196386994897, 98.902094334035326, 121.2741094217216, 101.18463497862281, 138.93502941970601, 120.71184773326806, 139.15404600347946, 139.56377827641663, 119.28279815624718, 99.338144106822554, 139.05438770927282, 138.95405784704622, 119.54614935118973, 139.9354467277665, 139.47260445000273, 100.02478729763811, 101.34605205591622, 138.97315450408186, 99.186025111246295, 140.53885845445572, 99.893009827114568]
>>> level_boundaries(z_vals)
[101.34605205591622, 121.2741094217216]
答案 7 :(得分:2)
只要你在Python的部分功能编程之后,考虑map,filter,reduce和zip ----都是在python中提供的。