用发电机构建矩阵

时间:2016-12-08 21:27:17

标签: python generator

我有一个清单:

l = [1,2,3]

我希望我的输出为:

m = [(1-1, 1-2, 1-3),(2-1, 2-2, 2-3), (3-1, 3-2, 3-3)]
m = [[0, -1, -2], [1,0,-1], [-2,-1,0]]

我写了这个函数,它工作正常:

def matrixer(l):
    matrix = []

    for data in l:
        column = []
        column.append(data - l[0])
        column.append(data - l[1])
        column.append(data - l[2])
        matrix.append(column)

    return matrix

但这并不能很好地扩展 - 因为我的列表可能有多达100个值,我不想继续为列表中的每个值添加以下代码行:

column.append(data - l[n])

我之前从未使用过发电机,但听起来解决方案只涉及一台发电机。我总是尝试过一段时间的循环,但是当我遇到同样的问题时,它并没有让我在那里。

4 个答案:

答案 0 :(得分:4)

使用两个for循环,我们每次都必须重置sub_answer。这看起来很乱,所以可能是另一种选择;可以在下面找到:

l = [1,2,3]
answer = []
for each in l:
  sub_answer = []
  for every in l:
    sub_answer.append(each-every)
  answer.append(sub_answer)
  sub_answer = []
print(answer)
#[[0, -1, -2], [1, 0, -1], [2, 1, 0]]

删除for循环以获得列表解析。现在我们不需要sub_answer

l = [1,2,3]
answer = []
for each in l:
  answer.append([each-x for x in l])
print(answer)
#[[0, -1, -2], [1, 0, -1], [2, 1, 0]]

l可扩展。我们正在迭代列表,然后追加到我们使用列表推导创建的新列表,我们通过再次浏览列表来减去each变量。

如果我们将l更改为l = [1,2,3,4,5,6,7],我们会:

[[0, -1, -2, -3, -4, -5, -6], [1, 0, -1, -2, -3, -4, -5], [2, 1, 0, -1, -2, -3, -4], [3, 2, 1, 0, -1, -2, -3], [4, 3, 2, 1, 0, -1, -2], [5, 4, 3, 2, 1, 0, -1], [6, 5, 4, 3, 2, 1, 0]]

作为备注(3-1 is not -2... it's 2....)

我们使用了一个列表理解为什么不使用两个?!?!?!: 如果你不想要for循环而只想使用列表理解:

l = [1,2,3]
print([[each-x for x in l] for each in l])
#[[0, -1, -2], [1, 0, -1], [2, 1, 0]]

给出相同的结果,但我认为如果您正在学习或在团队中,循环更具可读性。

答案 1 :(得分:2)

双列表理解在一行中完成:

def matrixer(l):
    return [[e - d for d in l] for e in l]
  • 内部listcomp创建内线
  • 外部listcomp创建行

输入结果:

[[0, -1, -2], [1, 0, -1], [2, 1, 0]]

列表推导是高度优化的记忆(更少的重新分配)& CPU方式(较少的指令)所以用这样的2个嵌套列表推导替换你的双循环+追加将大大加快你的代码。

答案 2 :(得分:2)

一个简短的答案(目前为止最短的^^)将是:

l = [1, 2, 3]

m = [[row - col for row in l] for col in l]

这使用list comprehension

答案 3 :(得分:1)

您可以将list comprehensionmap()operator一起使用,如下所示:

[map(operator.sub, [item]*len(l), l) for item in l]

这相当于:

matrix = []

for item in l:
    matrix.append(map(operator.sub, [item]*len(l), l))

<强>解释

对于item中的每个l,我们构建了一个列表[item]*len(l),我们使用map()operator来减去这两个列表。对于l中第一个为1的元素,我们有:

[1]*3  # => [1, 1, 1]

然后:

map(operator.sub, [1, 1, 1], [1, 2, 3])  # [1-1, 1-2, 1-3] => [0, -1, -2]

<强>输出:

>>> import operator
>>>
>>> l = [1, 2, 3]
>>> [map(operator.sub, [item]*len(l), l) for item in l]
[[0, -1, -2], [1, 0, -1], [2, 1, 0]]