我在python中有一个默认字典d
,其中包含两个列表,如下所示:
{
'data1': [0.8409093126477928, 0.9609093126477928, 0.642217399079215, 0.577003839123445, 0.7024399719949195, 1.0739533732043967],
'data2': [0.9662666242560285, 0.9235637581239243, 0.8947656867577896, 0.9266919525550584, 1.0220039913024457]
}
将来,默认字典中可能会有很多列表,例如data1
,data2
,data3
,data4
等。我需要比较默认字典的索引值彼此。因此,对于以上默认字典,我需要检查天气data1[0]->0.8409093126477928
是否小于data2[0]->0.9662666242560285
,其他索引也是如此,并将获胜列表索引的结果存储在单独的列表中,如下所示:
result = ['data1', 'data2', 'data1', 'data1', 'data1']
如果任何列表的长度大于其他列表的长度,我们只需要检查最后一个索引值是否小于1。就像data1[5]
无法与data2[5]
相比,因为没有data2[5]
的值,因此我们将简单地检查data1[5]
是否小于1。如果它小于1,那么我们将考虑将其添加到result
中,否则将其忽略,并且不会将其保存在result
中。
我想解决这个问题,就是从默认字典中提取列表到单独的列表,然后使用for循环比较索引值,但是当我执行print(d[0])
打印0th
索引列表时,它打印出[]
。为什么打印null。我如何比较上面的索引值。请帮忙。谢谢
答案 0 :(得分:1)
我们可以使用itertools中的zip_longest
和各种循环来获得结果:
from itertools import zip_longest
result = []
pairs = [[[z, y] for z in x] for y, x in data.items()]
for x in zip_longest(*pairs):
x = [y for y in x if y]
if len(x) > 1:
result.append(min(x, key=lambda x: x[0])[1])
elif x[0][0] < 1:
result.append(x[0][1])
print(result) # => ['data1', 'data2', 'data1', 'data1', 'data1']
首先,我们为每个字典值及其键中的每个项目创建对。这使以后获得结果键变得更加容易。我们zip_longest
遍历列表,过滤掉None
个。如果要比较的元素不止一个,则将min取并将其附加到结果中,否则我们检查lone元素并在其值小于1时保留它。
一个更可验证的例子是
data = {
'foo': [1, 0, 1, 0],
'bar': [1, 1, 1, 1, 0],
'baz': [1, 1, 0, 0, 1, 1, 0],
'quux': [0],
}
产生
['quux', 'foo', 'baz', 'foo', 'bar', 'baz']
按元素顺序,"quux"
赢得第0轮,"foo"
赢得第1轮,"baz"
第2轮,"foo"
第3轮归功于键顺序(与{{1}并列) }),第4轮为"baz"
。对于第5轮,"bar"
是最后一个排名,但不低于1,因此不采取任何措施。对于第6轮,"baz"
仍然是最后一位,但是因为0 <1,所以采取了这种方法。
答案 1 :(得分:1)
编辑:@ ggorlen建议,将自定义迭代器替换为zip_longest
我会这样使用custom_iterator来做到这一点,
item.index(min(item))
的第一个索引,然后获取对应于最小值keys[item.index(min(item))]
的键from itertools import zip_longest
keys = list(d.keys())
lengths = list(map(len,d.values()))
result = [keys[item.index(min(item))]
for i, item in enumerate(zip_longest(*d.values(), fillvalue=1))
if lengths[item.index(min(item))]>i]
result
如果要提供默认密钥而不是在找到的最小值不少于一个时跳过它
result = [keys[item.index(min(item))] if lengths[item.index(min(item))]>i else "NA"
for i, item in enumerate(zip_longest(*d.values(), fillvalue=1))]
答案 2 :(得分:1)
d = {
'd0': [0.1, 1.1, 0.3],
'd1': [0.4, 0.5, 1.4, 0.3, 1.6],
'd2': [],
}
import itertools
import collections
# sort by length of lists, shortest first and longest last
d = sorted(d.items(), key=lambda k:len(k[1]))
# loop through all combinations possible
for (key1, list1), (key2, list2) in itertools.combinations(d, 2):
result = []
for v1, v2 in itertools.zip_longest(list1, list2): # shorter list is padded with None
# no need to check if v2 is None because of sorting
if v1 is None:
result.append(key2 if v2 < 1 else None)
else:
result.append(key1 if v1 < v2 else key2)
# DO stuff with result, keys, list, etc...
print(f'{key1} vs {key2} = {result}')
输出
d2 vs d0 = ['d0', None, 'd0']
d2 vs d1 = ['d1', 'd1', None, 'd1', None]
d0 vs d1 = ['d0', 'd1', 'd0', 'd1', None]
我根据列表的长度对它们进行了排序。这样可以确保list1
总是更短或与list2
相同。
对于不同的长度,其余索引将是None
和key2
的混合。
但是,当元素相等时,将key2
添加到结果中。这可能不是理想的行为。
答案 3 :(得分:0)
会是这样吗
def compare2List(a, b):
'''
Input name of 2 lists that you need to compare
a = name of 1st list appearing in dict d
b = name of 2nd list appearing in dict d
'''
data1 = d[a]
data2 = d[b]
result = list()
i = 0
while i < len(data1) OR i < len(data2):
if i < len(data1) AND i < len(data2):
if data1[i] < data2[i]:
result.append("data1")
else:
result.append("data2")
else:
if i >= len(data1):
if data1[0] < 1:
result.append("data1")
elif i >= len(data2):
if data2[0] < 1:
result.append("data2")
i = i + 1
return result