如何在python中的默认字典中比较列表的索引值

时间:2019-09-29 02:31:59

标签: python list dictionary

我在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]
}

将来,默认字典中可能会有很多列表,例如data1data2data3data4等。我需要比较默认字典的索引值彼此。因此,对于以上默认字典,我需要检查天气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。我如何比较上面的索引值。请帮忙。谢谢

4 个答案:

答案 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来做到这一点,

  • zip每次迭代中从每个数组中获取最长的一项。对于较短的数组,当迭代超过其长度时将返回1
  • 列表遍历遍历迭代器并获得最小项item.index(min(item))的第一个索引,然后获取对应于最小值keys[item.index(min(item))]的键
  • 如果所选列表短于当前迭代器索引,则它会跳过或给出“ NA”值
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相同。

对于不同的长度,其余索引将是Nonekey2的混合。

但是,当元素相等时,将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