【问题标题】:Python: Problems with indexing a list of listPython:索引列表的问题
【发布时间】:2016-02-22 19:44:56
【问题描述】:

我有这个列表:

mylist=[[1, 2, 4, 8], [16, 32, 64, 128], [256, 512, 1024, 2048]]

现在我想创建一个字典,为每个键分配列表中相应索引的值。

在这种情况下:correct_dict={0:1,1:2,2:4,3:8,4:16,...,11:2048}

我打算用下面的函数来做:

def dictionarize3(array):
                dict3={}
                count_var=0
                for i in range(len(array[0]) - 1) :
                    for j in range(len(array[0]) - 1):
                        dict3[count_var]=array[i][j]
                        count_var=count_var+1
                return dict3

dict=dictionarize3(mylist)

但这就是我得到的: wrong_dict={0: 1, 1: 2, 2: 4, 3: 16, 4: 32, 5: 64, 6: 256, 7: 512, 8: 1024}.

所以,len(correct_dict)=12,而len(wrong_dict)=9

问题:是什么让我错过了列表中位于第三列的所有值?

【问题讨论】:

  • range(len(array[0]) - 1)) => range(3) 即 -> [0,1,2]。所以你错过了最后一个元素
  • 是的,但如果我去掉 -1,我会得到一个 out of index 错误。
  • 为什么是dict?如果您只是flatten 列表,您将获得一个具有完全相同索引和值的列表。例如。 itertools.chain(*mylist).
  • 未来,想想听写理解:{i: v for lst in mylist for i, v in enumerate(lst)}.
  • @FrancescoCastellani:这个Code like a Pythonista 很好读。

标签: python list dictionary indexing


【解决方案1】:

这是函数 dictionarize3 的更正版本:

def dictionarize3(array):
    dict3={}
    count_var=0
    for i in range(len(array)) :
        for j in range(len(array[i])):
            dict3[count_var]=array[i][j]
            count_var=count_var+1
    return dict3

您没有引用正确的部分。当试图找到整个数组的长度时,您会在数组中找到其中一个的长度,这只是一个逻辑错误。

编辑 正如 decltype_auto 所指出的,拥有一个额外的迭代变量来执行与已经在 for 循环中声明的函数相同的功能,这根本不是惯用的。我回答得太快了,我没有发现它!有替代和更高效的代码:

def dictionarize3(array):
dict3={}
for i in range(len(array)) :
    for j in range(len(array[i])):
        dict3[j]=array[i][j]
return dict3

【讨论】:

  • 这行得通。为什么j 需要达到比i 更高的索引?为什么我不能同时拥有len(array[0])?我试过了,我得到了一个超出索引的错误。但为什么呢?
  • 是不是因为我的列表就像一个 3x4 矩阵?那么,这两种长度不同吗?是这个吗?
  • 你为什么要进一步缩进return dict3?不应该和第一个for一致吗?
  • @FrancescoCastellani 我的错,现在修复它。
  • @R.Murray 好的,你回答了这个问题 - 毫无疑问。但是我可以建议您将我的替代代码添加到您的答案中吗?这个for i .. for j 在问题中有一个额外的计数器显然不是惯用的。
【解决方案2】:

字典理解和函数式编程风格的简单任务:

>>> mylist=[[1, 2, 4, 8], [16, 32, 64, 128], [256, 512, 1024, 2048]]
>>> correct_dict = {k:v for k, v in enumerate(reduce(lambda x,y: x+y, mylist))}
>>> correct_dict
{0: 1, 1: 2, 2: 4, 3: 8, 4: 16, 5: 32, 6: 64, 7: 128, 8: 256, 9: 512, 10: 1024, 11: 2048}

解释,您获取列表,将其简化为包含所有值的单个列表,使用相应的索引对其进行枚举,并以索引为键,列表编号为值进行字典理解。

【讨论】:

  • 改用functools.reduce
【解决方案3】:

如果每个列表的长度相同,您可以这样做:

d = dict((i1*4+i2, x) for i1, y in enumerate(mylist) for i2, x in enumerate(y))

【讨论】:

    【解决方案4】:
    >>> mylist=[[1, 2, 4, 8], [16, 32, 64, 128], [256, 512, 1024, 2048]]
    >>> l = []
    >>> for i in mylist:
            l.extend(i)
    >>> dict(zip(range(len(l)), l))
    

    【讨论】:

      【解决方案5】:

      dict 在这里似乎很不合适。一个简单的平面列表会给你同样的实际结果:

      [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048]
      

      这里lst[0]1lst[11]2048

      您可以像这样展平列表:

      lst = []
      for l in mylist:
         lst.extend(l)
      

      或:

      from itertools import chain
      lst = chain(*mylist)  # list(chain(*mylist)) if you don't want an iterator
      

      【讨论】:

        【解决方案6】:

        在你的情况下

        len(array[0]) = 4

        之后

        len(array[0]) - 1 = 3

        范围(3) = [0, 1, 2]

        并且您只使用列表的一部分 [1, 2, 4, 8]

        了解range

        【讨论】:

          【解决方案7】:

          这是itertools.chain 的工作

          from itertools import chain
          
          mylist=[[1, 2, 4, 8], [16, 32, 64, 128], [256, 512, 1024, 2048]]
          
          mydict = {i:v for i,v in enumerate(chain(*mylist))}
          
          print(mydict)
          

          输出:

          {0: 1, 1: 2, 2: 4, 3: 8, 4: 16, 5: 32, 6: 64, 7: 128, 8: 256, 9: 512, 10: 1024, 11: 2048}
          

          问题:是什么让我错过了列表中的所有价值观 位于第三列?

          range(len(array[0]) - 1)
          

          是一个在其参数之前以 1 结尾的范围;因此,在您的情况下,在 4 - 1 = 3 之前是一个,因此在索引 2 处,它会跳过内部索引为 3 的最后一个元素。

          编辑 还有那个外循环

          for i in range(len(array[0]) - 1) :
          

          出现工作只是巧合,因为外部列表长度为 3。 你需要的是这样的:

          for i in range(len(array)):
          

          您的“i”是针对整个外部数组,而不是针对它的第一个内部元素! :)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-08-17
            • 1970-01-01
            • 1970-01-01
            • 2017-10-04
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多