为了账号安全,请及时绑定邮箱和手机立即绑定

处理嵌套字典列表的最 Pythonic 方法是什么?

处理嵌套字典列表的最 Pythonic 方法是什么?

慕的地6264312 2023-10-11 21:21:18
识别 API 返回的不同嵌套字典类型以便应用正确类型的解析的最 Pythonic 方法是什么?我正在从 Reddit 进行 API 调用来获取 URL,并且正在获取具有不同键名称和不同嵌套字典结构的嵌套字典。我正在拉取我需要的 URL,但我需要一种更 Pythonic 的方式来识别嵌套字典的不同键名称和不同结构,因为if我在一个for循环中尝试的语句会遇到错误,因为“if”字典不包含key 我NoneType只是从if“询问”该键是否在字典中的语句中得到一个错误。在接下来的几段中,我描述了该问题,但您也许可以深入研究字典示例和下面的代码,并了解我无法一次性识别三种类型字典之一的问题。嵌套字典没有相同的结构,我的代码充满了trys 和我认为的冗余for循环。我有一个函数可以处理三种类型的嵌套字典。topics_data(下面使用)是一个 Pandas Dataframe,列是包含嵌套字典的vid列名称。topics_data有时,单元格中的对象vid是None我正在阅读的帖子是否不是视频帖子。API 仅返回三种主要类型的嵌套字典(如果没有None)。NoneType我最大的问题是,如果我尝试if使用以另一个键开头的键捕获嵌套字典的语句(reddit_video例如相反),则识别第一个键名称而不会出现错误oembed。由于这个问题,我为三种嵌套字典类型中的每一种迭代嵌套字典列表三次。我希望能够迭代嵌套字典列表一次,并一次性识别和处理每种类型的嵌套字典。下面是我得到的三种不同类型的嵌套字典的示例,以及我现在设置来处理它们的丑陋代码。我的代码可以工作,但很丑陋。请挖进去看看。嵌套字典...嵌套字典一{'reddit_video': {'fallback_url': 'https://v.redd.it/te7wsphl85121/DASH_2_4_M?source=fallback',  'height': 480,  'width': 480,  'scrubber_media_url': 'https://v.redd.it/te7wsphl85121/DASH_600_K',  'dash_url': 'https://v.redd.it/te7wsphl85121/DASHPlaylist.mpd?a=1604490293%2CYmQzNDllMmQ4MDVhMGZhODMyYmIxNDc4NTZmYWNlNzE2Nzc3ZGJjMmMzZGJjMmYxMjRiMjJiNDU4NGEzYzI4Yg%3D%3D&v=1&f=sd',  'duration': 17,  'hls_url': 'https://v.redd.it/te7wsphl85121/HLSPlaylist.m3u8?a=1604490293%2COTg2YmIxZmVmZGNlYTVjMmFiYjhkMzk5NDRlNWI0ZTY4OGE1NzgxNzUyMDhkYjFiNWYzN2IxYWNkZjM3ZDU2YQ%3D%3D&v=1&f=sd',  'is_gif': False,  'transcoding_status': 'completed'}}嵌套字典二{'type': 'gfycat.com', 'oembed': {'provider_url': 'https://gfycat.com',  'description': 'Hi! We use cookies and similar technologies ("cookies"), including third-party cookies, on this website to help operate and improve your experience on our site, monitor our site performance, and for advertising purposes. By clicking "Accept Cookies" below, you are giving us consent to use cookies (except consent is not required for cookies necessary to run our site).',  'title': 'Protestors in Hong Kong are cutting down facial recognition towers.',  'type': 'video',  'author_name': 'Gfycat',  'height': 600,  'width': 600,
查看完整描述

1 回答

?
拉丁的传说

TA贡献1789条经验 获得超8个赞

更新:意识到OP的文本正在处理非唯一的查找。添加了一段来描述如何做到这一点。


如果您发现自己多次循环字典列表来执行查找,请将列表重组为字典,以便查找成为键。例如这个:


a = [{"id": 1, "value": "foo"}, {"id": 2, "value": "bar"}]

for item in a:

    if item["id"] == 1:

        print(item["value"])

可以变成这样:


a = [{"id": 1, "value": "foo"}, {"id": 2, "value": "bar"}]

a = {item["id"]: item for item in a} # index by lookup field


print(a[1]["value"]) # no loop

... # Now we can continue to loopup by id eg a[2] without a loop

如果它是非唯一查找,您可以执行类似的操作:


indexed = {}

a = [{"category": 1, "value": "foo"}, {"category": 2, "value": "bar"}, {"category": 1, "value": "baz"}]

for item in a: # This loop only has to be executed once

    if indexed.get(item["category"], None) is not None:

        indexed[item["category"]].append(item)

    else:

        indexed[item["category"]] = [item]


# Now we can do:

all_category_1_data = indexed[1]

all_category_2_data = indexed[2]

如果出现索引错误,请使用默认字典索引来更轻松地处理


if a.get(1, None) is not None:

    print(a[1]["value"])

else:

    print("1 was not in the dictionary")

在我看来,这个 API 没有任何“Pythonic”,但如果 API 返回您需要循环的列表,那么它可能是一个设计糟糕的 API


更新:好的,我会尝试修复您的代码:


def download_vid(topics_data, ydl_opts):

    indexed_data = {'reddit': [], 'gfycat': [], 'thumbnail': []}


    for item in topics_data['vid']:

        if item.get('reddit_video', None) is not None:

            indexed_data['reddit'].append(item)

        elif item.get('type', None) == "gfycat.com":

            indexed_data['gfycat'].append(item)

        elif item.get('oembed', None) is not None:

            if item['oembed'].get('thumbnail_url', None) is not None:

                indexed_data['thumbnail'].append(item)


    for k, v in indexed_data.items():

        assert k in ('reddit_video', 'gfycat', 'thumbnail')

        if k == 'reddit_video':

            B = v['reddit_video']['fallback_rul']

            ...

        elif k == 'gfycat':

            C = v['oembed']['thumbnail_url']

            ...

        elif k == 'thumbnail':

            D = v['oembed']['thumbnail_url']

            ...

以防万一不清楚为什么这样更好:

  • OP 循环了 topic_data['vid'] 3 次。我做了两次。

  • 更重要的是,如果加更多的题目,我仍然只做两次。OP将不得不再次循环。

  • 无异常处理。

  • 现在每组对象都已编入索引。所以OP可以做,例如indexed_data['gfycat']来获取所有这些对象(如果需要的话),这是一个哈希表查找,所以它很快


查看完整回答
反对 回复 2023-10-11
  • 1 回答
  • 0 关注
  • 87 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信