【问题标题】:How to compare index values of list in default dict in python如何比较python中默认dict中列表的索引值
【发布时间】:2019-09-29 02:31:59
【问题描述】:

我在 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 索引列表时,它打印出@ 987654339@。为什么它打印空。如何比较上面的索引值。请帮忙。谢谢

【问题讨论】:

  • 这可能有助于解决您的问题:How to index into a dictionary?
  • 当列表比其他列表更长时,我可以澄清一下该怎么做。只有在剩下一个列表或缺少任何列表时,我们才做“小于 1”的事情吗?如果是后者,我们选择剩下的哪一个?
  • 当它们相等时会发生什么?

标签: python list dictionary


【解决方案1】:

编辑:按照@ggorlen 的建议,将自定义迭代器替换为 zip_longest

我会像这样使用 custom_iterator 来做到这一点,

  • 在每次迭代中从每个数组中压缩最长的项目。对于较短的数组,当迭代超过其长度时,它将返回 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))]

【讨论】:

  • 谢谢。你能解释一下这个逻辑吗?
  • 在我的帖子中的示例中运行此程序得到了不同的结果:['quux', 'foo', 'baz', 'foo', 'bar', 'foo', 'baz']。不知道最后一个"foo" 是如何进入的。我认为使用col.append(arr[i] if i< len(arr) else 1) 填充会破坏逻辑,因为默认占位符值 1 可能会无意中被解释为最小值并产生误报,但我不是 100% 确定。
  • @DevKhadka 我得到了正确的结果['data1', 'data2', 'data1', 'data1', 'data1', 'data2'],但不确定为什么将data2 附加为result 中的最后一项。另外我还在尝试理解这个逻辑,你能解释一下你在结果列表中究竟是在哪里附加data1data2 吗?
  • @SAndrew 你能评论我回复的正确性吗?我很好奇我的示例是否符合您的要求。如果是这样,它应该适合你。
  • 迭代器为较短的列表提供默认值 1,因此当迭代器经过较短的列表并且其他列表的值大于 1 时,它将选择第一个列表的键
【解决方案2】:

我们可以使用来自 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']

首先,我们在每个 dict 值及其键中创建每个项目的对。这使得以后更容易获得结果键。我们zip_longest 并遍历列表,过滤掉Nones。如果我们有多个要比较的元素,我们将取最小值并将其附加到结果中,否则我们检查唯一的元素并在其值小于 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 轮,这要归功于关键顺序(与 "baz" 并列),"bar" 用于第 4 轮。对于第 5 轮,"baz" 是最后一个站着但不低于 1,所以没有采取任何措施。在第 6 轮中,"baz" 仍然是最后一位,但由于 0

【讨论】:

    【解决方案3】:
    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 会添加到结果中。这可能不是我们想要的行为。

    【讨论】:

      【解决方案4】:

      可以这样吗

      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
      

      【讨论】:

      • 谢谢,但正如我提到的,可以有多个data1data2data3.. 所以我们不能在逻辑中静态使用 data1 或 data2
      • default_dict 可以有 n 个数据集,所以这不起作用。
      • 可以像我上面编辑的代码一样吗?或者您需要比较出现在 dict d 中的所有对
      猜你喜欢
      • 2012-07-10
      • 2014-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多