【问题标题】:How to iterate over nested dictionaries in a LIST, using for loop如何使用 for 循环遍历 LIST 中的嵌套字典
【发布时间】:2021-04-13 06:04:45
【问题描述】:

我想使用 for 循环提取每个字典的第二个键。但是,字典嵌套在一个列表中(见下文)。另外,请注意第二个键并不总是相同的。

video_Ids = [
{'kind': 'youtube#playlist',
  'playlistId': 'PLt1O6njsCRR-D_1jUAhJrrDZyYL6OZSGa'},
 {'kind': 'youtube#playlist',
  'playlistId': 'PLt1O6njsCRR_8oi7E6qnPWGQbn8NoQ6sG'},
 {'kind': 'youtube#channel', 'channelId': 'UC4i5R6-IW05iiU8Vu__vppA'},
 {'kind': 'youtube#video', 'videoId': 'XquM0L2WUio'},
 {'kind': 'youtube#video', 'videoId': '05yrGVZ96b4'}
]

我尝试了不同的方法,但到目前为止都没有奏效。这是我的最后一次尝试:删除要留下的第一个键以及包含第二个键的列表。

for i in video_Ids:
    if video_Ids["kind"] == "youtube#video":
        del video_Ids[i]["kind"]
    elif video_Ids[i]["kind"] == "youtube#playlist":
        del video_Ids[i]["kind"]
    elif video_Ids[i]["kind"] == "youtube#channel":
        del video_Ids[i]["kind"]

这是我收到的信息:

TypeError: list indices must be integers or slices, not str

我尽了最大的努力,现在卡住了几天。非常感谢任何帮助,谢谢。

【问题讨论】:

  • 在您提供的代码中 i 是字典而不是数字(不是索引),要解决此问题,您可以执行 range(len(video_Ids))

标签: python python-3.x dictionary for-loop nested


【解决方案1】:

一旦有了字典,就不需要使用索引了:

for video in video_Ids:
    if video["kind"] == "youtube#video":
        del video["kind"]
    elif video["kind"] == "youtube#playlist":
        del video["kind"]
    elif video["kind"] == "youtube#channel":
        del video["kind"]

要提取第二个键,您需要对每个字典进行迭代。例如:

from itertools import islice
secondKeys = [ {k:v} for d in video_Ids for k,v in islice(d.items(),1,2)]

# or without itertools ...

secondKeys = [ {k:v} for d in video_Ids for _,(k,v),*_ in [d.items()]]
    
print(secondKeys)
[{'playlistId': 'PLt1O6njsCRR-D_1jUAhJrrDZyYL6OZSGa'},
 {'playlistId': 'PLt1O6njsCRR_8oi7E6qnPWGQbn8NoQ6sG'},
 {'channelId': 'UC4i5R6-IW05iiU8Vu__vppA'},
 {'videoId': 'XquM0L2WUio'},
 {'videoId': '05yrGVZ96b4'}]

或者,如果你只想要键而不是对应的值:

from itertools import islice
secondKeys = [ k for d in video_Ids for k in islice(d,1,2)]

# or without itertools ...

secondKeys = [ k for d in video_Ids for _,k,*_ in [d]]

print(secondKeys)
['playlistId', 'playlistId', 'channelId', 'videoId', 'videoId']

【讨论】:

    【解决方案2】:

    有两种方法可以修复您的代码:

    版本 1

    video_Ids = [
    {'kind': 'youtube#playlist',
      'playlistId': 'PLt1O6njsCRR-D_1jUAhJrrDZyYL6OZSGa'},
     {'kind': 'youtube#playlist',
      'playlistId': 'PLt1O6njsCRR_8oi7E6qnPWGQbn8NoQ6sG'},
     {'kind': 'youtube#channel', 'channelId': 'UC4i5R6-IW05iiU8Vu__vppA'},
     {'kind': 'youtube#video', 'videoId': 'XquM0L2WUio'},
     {'kind': 'youtube#video', 'videoId': '05yrGVZ96b4'}
    ]
    
    
    
    for id in video_Ids:
        if id["kind"] == "youtube#video":
            del id["kind"]
        elif id["kind"] == "youtube#playlist":
            del id["kind"]
        elif id["kind"] == "youtube#channel":
            del id["kind"]
    

    版本2

    video_Ids = [
    {'kind': 'youtube#playlist',
      'playlistId': 'PLt1O6njsCRR-D_1jUAhJrrDZyYL6OZSGa'},
     {'kind': 'youtube#playlist',
      'playlistId': 'PLt1O6njsCRR_8oi7E6qnPWGQbn8NoQ6sG'},
     {'kind': 'youtube#channel', 'channelId': 'UC4i5R6-IW05iiU8Vu__vppA'},
     {'kind': 'youtube#video', 'videoId': 'XquM0L2WUio'},
     {'kind': 'youtube#video', 'videoId': '05yrGVZ96b4'}
    ]
    
    
    
    for i in range(len(video_Ids)): #iterate over a range instead 
        if video_Ids[i]["kind"] == "youtube#video":
            del video_Ids[i]["kind"]
        elif video_Ids[i]["kind"] == "youtube#playlist":
            del video_Ids[i]["kind"]
        elif video_Ids[i]["kind"] == "youtube#channel":
            del video_Ids[i]["kind"]
    

    从这些示例中您可以看到,您可以遍历根据列表长度创建的数组并提供索引,或者直接遍历列表,但是 id 不是索引,而是当前字典。

    【讨论】:

      【解决方案3】:

      试试这个:

      video_Ids = [
      {'kind': 'youtube#playlist',
      'playlistId': 'PLt1O6njsCRR-D_1jUAhJrrDZyYL6OZSGa'},
      {'kind': 'youtube#playlist',
      'playlistId': 'PLt1O6njsCRR_8oi7E6qnPWGQbn8NoQ6sG'},
      {'kind': 'youtube#channel', 'channelId': 'UC4i5R6-IW05iiU8Vu__vppA'},
      {'kind': 'youtube#video', 'videoId': 'XquM0L2WUio'},
      {'kind': 'youtube#video', 'videoId': '05yrGVZ96b4'}
      ]
      
      list_of_keys = []
      
      for _, second_key in video_Ids:
          list_of_keys.append(second_key)
      

      打印:

      ['playlistId', 'playlistId', 'channelId', 'videoId', 'videoId']
      

      如果你也想要这个值,写这个:

      list_of_keys = []
      
      for index, _ in enumerate(video_Ids):
          list_of_keys.append(list(video_Ids[index].items())[1])
      

      打印:

      [('playlistId', 'PLt1O6njsCRR-D_1jUAhJrrDZyYL6OZSGa'), ('playlistId', 'PLt1O6njsCRR_8oi7E6qnPWGQbn8NoQ6sG'), ('channelId', 'UC4i5R6- IW05iiU8Vu__vppA'), ('videoId', 'XquM0L2WUio'), ('videoId', '05yrGVZ96b4')]
      

      【讨论】:

        【解决方案4】:

        正如其他人所指出的,您的 if 语句中似乎也存在错误。由于 video_Ids 的元素是字典,i 将是字典,所以你的 if 语句应该引用 i["kind"] 而不是 video_Ids[i]["kind"]

        不过,更重要的是,您永远不应该依赖字典键的特定顺序。从 python 3.7 开始,键将按照它们被插入的顺序保存,但这并不意味着它们是按字母顺序或任何东西排序的。这不是字典的重点。有关更多背景信息,请参阅docs on data typesthis question on dictionary key ordering 的答案。

        如果您知道字典将有两个键,其中一个是“kind”,那么您总是可以遍历这些键以找到不是“kind”的键名称,例如:

        # optional test to check for 2 keys
        assert len(i) == 2, f"Number of keys does not equal 2: {i.keys()}"
        
        # filter the keys for the one that isn't "kind" and extract the result
        other_key=[k for k in i.keys() if k != 'kind'][0]
        

        如果你把它放在你的 for 循环中,你应该有另一个键的名称,你可以用它来引用未知元素为 i[other_key]

        另一种选择是使用数据内部的结构来构造键。似乎 kind 实际上可以用于构造另一个键 - 这似乎是您的数据的预期布局。因此,在数据中检索 ID 的另一种选择是在每个循环元素中构造键:

        # use last part of kind, starting from end of "youtube#" substring
        media_type = i["kind"][len("youtube#"):]
        
        media_id_key = media_type + "ID"
        media_id = i[media_id_key]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-13
          • 2022-08-17
          • 2021-11-20
          • 2013-02-20
          • 2011-03-18
          相关资源
          最近更新 更多