Python:在列表列表中相互添加列表值

时间:2014-07-18 01:18:16

标签: python list

我有一个像这样的列表列表:

[[12411.0, 31937.0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.15, 0.1, 0.15, 0.2, 0.1, 0.15, 0.15, 0.15, 0.15], [12411.0, 31937.0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]], etc.]

如果内部列表的第一个和第二个元素与另一个内部列表的第一个和第二个元素相同(如上例所示),我想创建一个函数来添加剩余的值并将它们合并到一个列表中。示例输出如下:

[12411.0, 31937, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.25, 0.2, 0.25, 0.3, 0.2, 0.25, 0.25, 0.25, 0.25]

我很难告诉Python如何在将它们合并之前初始识别并比较列表中的两个元素。到目前为止,这是我最好的尝试:

def group(A):
for i in range(len(A)):
    for j in range(len(A[i])):
        if A[i][0:1] == A[i: ][0:1]:
            return [A[i][0], A[i][1], sum(A[i][j+2], A[i: ][j+2])]

我相信,由于代码的A [i:]和A [i:] [j + 2]部分,我得到索引错误。我不知道如何用Python来表达它,告诉函数添加符合条件的任何其他行。

4 个答案:

答案 0 :(得分:3)

这是一种方法:

>>> a_list = [[12411.0, 31937.0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.15, 0.1, 0.15, 0.2, 0.1, 0.15, 0.15, 0.15, 0.15], [12411.0, 31937.0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]]
>>> result = [a + b for a, b in zip(*a_list)]
>>> result[:2] = a_list[0][:2]
>>> result
[12411.0, 31937.0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.25, 0.2, 0.25, 0.30000000000000004, 0.2, 0.25, 0.25, 0.25, 0.25]

这可以通过以下方式盲目地在所有子列表中添加相应的元素:

[a + b for a, b in zip(*a_list)]

然后重写结果的前两个元素,根据问题没有改变,通过这样做:

result[:2] = a_list[0][:2]

从您的问题来看,如果子列表的前两个元素不匹配,行为应该是什么,这一点并不明显。但是下面的代码片段将帮助您检查子列表的前两个元素是否匹配。假设a_list包含前两个元素不匹配的子列表:

>>> a_list = [[12411.0, 31937.0, 0.1, 0.1], [12411.3, 31937.0, 0.1, 0.1]]

然后,这个条件:

all([True if list(a)[1:] == list(a)[:-1] else False for a in list(zip(*a_list))[:2]])

将返回False。否则True。代码提取所有子列表的第一个元素和第二个元素,然后检查它们是否相等。

您可以在代码中包含上述检查,并根据预期行为相应地修改代码。

总结一下:

a_list = [[12411.0, 31937.0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.15, 0.1, 0.15, 0.2, 0.1, 0.15, 0.15, 0.15, 0.15], [12411.0, 31937.0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]]
check = all([True if list(a)[1:] == list(a)[:-1] else False for a in list(zip(*a_list))[:2]])
result = []
if check:
    result = [a + b for a, b in zip(*a_list)]
    result[:2] = a_list[0][:2]
else:
    # whatever the behavior should be.

答案 1 :(得分:3)

这是一个合并前两个条目匹配的所有子列表的函数。它还处理子列表长度不同的情况:

from itertools import izip_longest

l = [[1,3,4,5,6], [1,3,2,2,2], [2,3,5,6,6], [1,1,1,1,1], [1,1,2,2,2], [1,3,6,2,1,1,2]]
l2 = [[12411.0, 31937.0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.15, 0.1, 0.15, 0.2, 0.1,  0.15, 0.15, 0.15, 0.15], [12411.0, 31937.0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]]

def merge(l):
    d = {}
    for ent in l:
        key = tuple(ent[0:2])
        merged = d.get(key, None)
        if merged is None:
            d[key] = ent
        else:
            merged[2:] = [a+b for a,b in izip_longest(merged[2:], ent[2:], fillvalue=0)]
    return d.values()

print merge(l)
print merge(l2)

输出:

[[1, 3, 12, 9, 9, 1, 2], [2, 3, 5, 6, 6], [1, 1, 3, 3, 3]]
[[12411.0, 31937.0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.25, 0.2, 0.25, 0.30000000000000004, 0.2, 0.25, 0.25, 0.25, 0.25]]

通过维护一个dict来实现,其中键是子列表的前两个条目(存储为元组)。当我们遍历子列表时,我们检查是否在dict中有一个条目。如果没有,我们将当前子列表存储在dict中。如果已有条目,我们将从索引2开始的所有值相加,并更新dict。一旦我们进行了一次迭代,我们只需返回dict中的所有值。

答案 2 :(得分:1)

这是一个功能,它会使用列表A并使用您的条件检查内部列表ij。然后,如果前两个元素不匹配,它将返回您想要的总和列表,或None

def check_internal_ij(A,i,j):
    """ checks internal list i against internal list j """ 
    if A[i][0:2] == A[j][0:2]:
        new = [x+y for x,y in zip( A[i], A[j] )]
        new[0:2] = A[i][0:2]
        return new
    else:
        return None

然后,您可以在要检查的所有内部列表组合上运行该功能。

答案 3 :(得分:1)

如果您喜欢itertools并付出一点努力,可以通过使用groupbyisliceizipimap来轻松解决这个问题。和chain

当然,您还应该记得使用operator.itemgetter

<强>实施

# Create a group of lists where the key (the first two elements of the lists) matches
groups = groupby(sorted(l, key = itemgetter(0, 1)), key = itemgetter(0, 1))
# zip the lists and then chop of the first two elements. Sum the elements of the resultant list
# Remember to add the newly accumulated list with the first two elements
groups_sum = ([k, imap(sum, islice(izip(*g), 2, None))] for k, g in groups )
# Reformat the final list to match the output format
[list(chain.from_iterable(elem)) for elem in groups_sum]

实施(如果您是单班轮的粉丝)

[list(chain.from_iterable([k, imap(sum, islice(izip(*g), 2, None))]))
  for k, g in groupby(sorted(l, key = itemgetter(0, 1)), key = itemgetter(0, 1))]

示例输入

l = [[10,20,0.1,0.2,0.3,0.4],
     [11,22,0.1,0.2,0.3,0.4],
     [10,20,0.1,0.2,0.3,0.4],
     [11,22,0.1,0.2,0.3,0.4],
     [20,30,0.1,0.2,0.3,0.4],
     [10,20,0.1,0.2,0.3,0.4]]

示例输出

[[10, 20, 0.3, 0.6, 0.9, 1.2],
 [11, 22, 0.2, 0.4, 0.6, 0.8],
 [20, 30, 0.1, 0.2, 0.3, 0.4]]

<强>解剖

groups = groupby(sorted(l, key = itemgetter(0, 1)), key = itemgetter(0, 1))
# After grouping, similar lists gets clustered together
[((10, 20),
  [[10, 20, 0.1, 0.2, 0.3, 0.4],
   [10, 20, 0.1, 0.2, 0.3, 0.4],
   [10, 20, 0.1, 0.2, 0.3, 0.4]]),
 ((11, 22), [[11, 22, 0.1, 0.2, 0.3, 0.4], [11, 22, 0.1, 0.2, 0.3, 0.4]]),
 ((20, 30), [[20, 30, 0.1, 0.2, 0.3, 0.4]])]

groups_sum = ([k, imap(sum, islice(izip(*g), 2, None))] for k, g in groups )
# Each group is accumulated from the second element onwards
[[(10, 20), [0.3, 0.6, 0.9, 1.2]],
 [(11, 22), [0.2, 0.4, 0.6, 0.8]],
 [(20, 30), [0.1, 0.2, 0.3, 0.4]]]

[list(chain.from_iterable(elem)) for elem in groups_sum]
# Now its just a matter of representing in the output format
[[10, 20, 0.3, 0.6, 0.9, 1.2],
 [11, 22, 0.2, 0.4, 0.6, 0.8],
 [20, 30, 0.1, 0.2, 0.3, 0.4]]