对数组执行操作并将结果存储在列表列表

时间:2018-04-02 15:47:19

标签: python python-3.x

所以我想多次对列表执行操作,以便我的输出是包含可能的输出组合的列表列表。在这种情况下,我想从列表中减去一次值,但是为每个元素重复一次。所以在这个例子中我想从列表中的一个元素中减去一个,存储它,然后重复下一个元素:

input1 = [1, 2, 3, 0, 4]
output1 = [[0, 2, 3, 0, 4], [1, 1, 3, 0, 4], [1, 2, 2, 0, 4], [1, 2, 3, 0, 3]]

这些值将始终为整数,如果值小于1,则函数不会从中减去。

现在我有一个while循环,每当input1中的值为> = 1时,就会使用列表input1填充列表。我做了第二次while循环尝试完成减法,但它只是从任何数字> = 1中减去1。

i = 0
input1 = [1, 2, 3, 0, 4]
output1 = []
while i < int(len(input1)):
    if input1[i] >= 1:
        print('i: ' + str(i))
        print(input1[i])
        output1.append(input1)
    i += 1
print(output1)
j = 0
k = 0
while j < int(len(output1)) or k < int(len(input1)):
    print('j: ' + str(j) + ', k: ' + str(k))
    if output1[j][k] < 1:
        print(output1[j][k])
        k += 1
    elif output1[j][k] >= 1:
        output1[j][k] = output1[j][k] - 1
        print(output1[j][k])
        k += 1
        j += 1
print(output1)

使用此代码,在最后一行output1上打印:

[[0, 1, 2, 0, 3], [0, 1, 2, 0, 3], [0, 1, 2, 0, 3], [0, 1, 2, 0, 3]]

这里出了什么问题?有没有更有效的方法来做到这一点,也许使用itertools?

3 个答案:

答案 0 :(得分:3)

以下是一些代码,它使用enumerate生成器来提供比其他方式更具Pythonic的代码。 enumerate返回一对数字:第一个是列表中项目的索引,第二个是项目本身。

input1 = [1, 2, 3, 0, 4]
output1 = []
for ndx, item in enumerate(input1):
    if item >= 1:
        tempoutput = input1[:]  # a copy of the list
        tempoutput[ndx] -= 1
        output1.append(tempoutput)

变量output1现在具有所需的值,

[[0, 2, 3, 0, 4], [1, 1, 3, 0, 4], [1, 2, 2, 0, 4], [1, 2, 3, 0, 3]]

您的原始代码不起作用,因为您犯了一个常见的错误。您使用

在第一部分中构建output1
output1.append(input1)

但只是将另一个引用添加到output1的输入列表,而不是添加输入列表的副本。当您更改output1的任何一个子列表时,它们都会同时被修改,因为它们实际上都是相同的列表。您应该使用

添加输入列表的副本
output1.append(input1[:])

(请注意,我在代码中使用相同的技巧来获取列表的副本。)当对代码进行了更改时,它会给出正确的答案。

答案 1 :(得分:3)

如果您乐意使用第三方库,numpy很方便:

import numpy as np

input1 = np.array([1, 2, 3, 0, 4])

n = len(input1)
arr = np.tile(input1, (n, 1))
res = (arr - np.eye(n))[np.where(input1 >= 1)]

<强>结果

array([[ 0.,  2.,  3.,  0.,  4.],
       [ 1.,  1.,  3.,  0.,  4.],
       [ 1.,  2.,  2.,  0.,  4.],
       [ 1.,  2.,  3.,  0.,  3.]])

<强>解释

  • 使用numpy.tile创建一个形状为(n, n)的数组。
  • 减去身份numpy.eye以从对角线中减去1。
  • 使用numpy.where过滤正输入。

为什么要使用numpy?

  • 性能:Python循环比矢量化numpy计算慢。
  • 内存:numpy比Python列表更有效地保存数字数据。
  • 语法:专注于数字逻辑而不是多个for&amp; if陈述。

答案 2 :(得分:2)

这是一个基本版本,可以完成你所描述的内容,改进它是留给读者的练习:

input = [1, 2, 3, 0, 4]
output = []

for i, item in enumerate(input):
    current = input[:]
    current[i] = item - 1 if item > 0 else item
    output.append(current)

编辑:如果评论所暗示的当前元素小于1,则应跳过整个操作,解决方案将变为:

input = [1, 2, 3, 0, 4]
output = []

for i, item in enumerate(input):
    if item > 0:
        current = input[:]
        current[i] -= 1
        output.append(current)