比较一个列表中的子列表元素并返回一个列表

4
我有一个列表,其中包含了多个子列表,我不知道主列表的长度,但是每个子列表都包含了6个浮点数。我需要比较每个子列表中的浮点数,并将前三个浮点数中的最小值和后三个浮点数中的最大值保留下来,最终以相同的顺序将所有这些值返回到一个6个浮点数的列表中。
以下是一个例子:
list1 = [[-2.0, 0.0, -2.0, 2.0, 10.0, 2.0], [-1.0, 0.0, 2.0, 1.0, 5.0, 4.0]]
# Compare list1[0][0] with list1[1][0]
# Will return -2.0 (because the index is between 0 and 2 so it returns the lower float)
# Compare list1[0][4] with list1[1][4]
# Will return 10.0 (because the index is between 3 and 5 so it returns the higher float)
# The final result which should be returned is:
# [-2.0, 0.0, -2.0, 2.0, 10.0, 4.0]

list2 = [[-2.0, 0.0, -2.0, 2.0, 10.0, 2.0], [-1.0, 0.0, 2.0, 1.0, 5.0, 4.0], [3.0, 0.0, -1.0, 4.0, 1.0, 0.0]]
# Compare list2[0][2] with list2[1][2] with list2[2][2]
# Will return -2.0 (because the index is between 0 and 2 so it returns the lower float)
# The final result which should be returned is:
# [-2.0, 0.0, -2.0, 4.0, 10.0, 4.0]

我在这个网站上阅读了有关zip()、集合、列表推导式以及其他不同主题的内容,但是我无法实现我想要的功能。


2
  1. 添加你的尝试。
  2. 添加最终期望输出。
- Bhargav Rao
@ Bhargav Rao - 抱歉,我添加了我希望返回的结果。但是我承认在没有任何令人信服的尝试之前就放弃了... - UKDP
3个回答

6
如果你执行zip(*list2),你将会得到一个列表,其中包含每个子列表的第一个元素、第二个元素等等。因此,你需要获取前三个元素的最小值和后三个元素的最大值。
zipped = zip(*list2)
result = [min(zipped[i]) for i in range(3)] + [max(zipped[i]) for i in range(3, 6)]

在Python 3中,zip()会像迭代器一样延迟获取压缩的子列表,而在Python 2中它会提前创建整个列表。这类似于两个版本之间的range()。如果你想在Python 2中进行惰性生成,可以使用itertools模块中的迭代器版本。
import itertools

zipped = itertools.izip(*list2)
result = [min(zipped.next()) for _ in range(3)] + [max(zipped.next()) for _ in range(3)]

编辑:展示zip()函数的视觉效果。

>>> a = [[1, 2, 3], [4, 5, 6]]
>>> zip(*a) # you need `list(zip(*a))` in Python 3
[(1, 4), (2, 5), (3, 6)]

星号语法会将列表解包成多个参数,因此 zip(*[[1, 2, 3], [4, 5, 6]]) 就变成了 zip([1, 2, 3], [4, 5, 6]),这正是你想要的。

谢谢!第一个方案非常完美,现在我更容易理解了。但是我也会去看看你的第二个方案。 :) - UKDP
1
@UKDP 我已经更新了我的回答,提到Python 3中的zip()行为有些不同。为了理解这一点以及itertools.izip(),您需要查看迭代器和生成器 - Reti43

1
你可以使用两个嵌套的for循环“手动”完成它。
list1 = [[-2.0, 0.0, -2.0, 2.0, 10.0, 2.0], [-1.0, 0.0, 2.0, 1.0, 5.0, 4.0]]
output = [0 for x in range(6)]
# iterate over the 6 numbers
for i in range(6):
    value = list1[0][i] # pick the first number
    #iterate over all the lists, if we find a bigger/smaller one our current one then save it
    for j in range(len(list1)):
        if i >= 3 and list1[j][i] > value:
                value = list1[j][i]
        elif i < 3 and list1[j][i] < value:
                value = list1[j][i]
    #put the biggest/smallest value in the correct place in the output array
    output[i] = value
print output

0

NumPy解决方案

您可以使用NumPy:

np.concatenate((np.min(a[:,:3], axis=0), np.max(a[:,3:], axis=0)))

完整示例

import numpy as np

list1 = [[-2.0, 0.0, -2.0, 2.0, 10.0, 2.0], [-1.0, 0.0, 2.0, 1.0, 5.0, 4.0]]
list2 = [[-2.0, 0.0, -2.0, 2.0, 10.0, 2.0], [-1.0, 0.0, 2.0, 1.0, 5.0, 4.0],
         [3.0, 0.0, -1.0, 4.0, 1.0, 0.0]]

a1 = np.array(list1)
a2 = np.array(list2)

for a in [a1, a2]:
    print(list(np.concatenate((np.min(a[:,:3], axis=0), np.max(a[:,3:], axis=0)))))

输出:

[-2.0, 0.0, -2.0, 2.0, 10.0, 4.0]
[-2.0, 0.0, -2.0, 4.0, 10.0, 4.0]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接