【问题标题】:flatten a list of nested ordered dictionaries in python展平python中的嵌套有序字典列表
【发布时间】:2019-05-09 07:49:56
【问题描述】:

我有点困惑如何从 Python 中的有序列表的嵌套列表中提取信息。例如:

list_of_interest = [OrderedDict([('name', 'Viscozyme'), ('company', 'Roche (Chile)')]),
 [OrderedDict([('name', 'Davictrel'), ('company', None)]),
  OrderedDict([('name', 'Enbrel Sureclick'), ('company', None)]),
  OrderedDict([('name', 'Tunex'), ('company', None)])],
 OrderedDict([('name', 'Angiox'), ('company', None)]),
 [OrderedDict([('name', 'Enantone'), ('company', None)]),
  OrderedDict([('name', 'Leuplin'), ('company', 'Takeda')]),
  OrderedDict([('name', 'LeuProMaxx'), ('company', 'Baxter/Teva')]),
  OrderedDict([('name', 'Leupromer'), ('company', None)]),
  OrderedDict([('name', 'Lutrate'), ('company', None)]),
  OrderedDict([('name', 'Memryte'), ('company', 'Curaxis')]),
  OrderedDict([('name', 'Prostap 3'), ('company', 'Takeda UK')]),
  OrderedDict([('name', 'Prostap SR'), ('company', 'Takeda UK')]),
  OrderedDict([('name', 'Viadur'), ('company', 'Bayer AG')])],
 OrderedDict([('name', 'Geref'), ('company', 'Serono Pharma')])]

我需要提取'name'下的所有项目。

所以我需要一个函数:

get_names(list_of_interest) --> ['Viscozyme', 'Davictrel', 'Enbrel Sureclick', 'Tunex', 'Angiox', 'Enantone', ..., 'Geref']

老实说,我尝试了嵌套列表推导、生成器表达式甚至 pandas 数据框,但都失败了,因为一些子列表是单个值。

【问题讨论】:

  • 显示你尝试过的代码
  • 由于 OP 不是关于真正的嵌套字典(它是一个嵌套列表),因此这不是我所引用的真正副本。

标签: python list dictionary


【解决方案1】:
from collections import OrderedDict

list_of_interest =\
    [OrderedDict([('name', 'Viscozyme'), ('company', 'Roche (Chile)')]),
    [OrderedDict([('name', 'Davictrel'), ('company', None)]),
     OrderedDict([('name', 'Enbrel Sureclick'), ('company', None)]),
     OrderedDict([('name', 'Tunex'), ('company', None)])],
     OrderedDict([('name', 'Angiox'), ('company', None)]),
    [OrderedDict([('name', 'Enantone'), ('company', None)]),
     OrderedDict([('name', 'Leuplin'), ('company', 'Takeda')]),
     OrderedDict([('name', 'LeuProMaxx'), ('company', 'Baxter/Teva')]),
     OrderedDict([('name', 'Leupromer'), ('company', None)]),
     OrderedDict([('name', 'Lutrate'), ('company', None)]),
     OrderedDict([('name', 'Memryte'), ('company', 'Curaxis')]),
     OrderedDict([('name', 'Prostap 3'), ('company', 'Takeda UK')]),
     OrderedDict([('name', 'Prostap SR'), ('company', 'Takeda UK')]),
     OrderedDict([('name', 'Viadur'), ('company', 'Bayer AG')])],
     OrderedDict([('name', 'Geref'), ('company', 'Serono Pharma')])]

names = []
for item in list_of_interest:
    if isinstance(item, OrderedDict):
        names.append(item['name'])
    else:
        for list_ord_dict in item:
            names.append(list_ord_dict['name'])

print(names)
#['Viscozyme', 'Davictrel', 'Enbrel Sureclick', 'Tunex', 'Angiox', 'Enantone', 'Leuplin', 'LeuProMaxx', 'Leupromer', 'Lutrate', 'Memryte', 'Prostap 3', 'Prostap SR', 'Viadur', 'Geref']

你有两种类型的项目,你可以通过你的主列表知道迭代和打印类型。如果你有更多的深度,你可以使用一个递归函数,当遇到一个列表时会调用它自己。对于您提供的数据集,上面的代码可以正常工作。

【讨论】:

    【解决方案2】:

    试试这个:

    def flat(l):
        ret = list()
        for ll in l:
            if isinstance(ll, (OrderedDict, list)):
                ret.extend(flat(ll))
            else:
                ret.append(ll)
        return ret
    

    它应该适用于任何深度的列表

    【讨论】:

    • 你为什么要检查是否是 OrderedDict 的实例?然后,您的函数将仅遍历 dict 的键
    【解决方案3】:

    您可以使用自定义递归函数展平嵌套列表:

    def flatten(l):
        for el in l:
            if isinstance(el, list):
                yield from flatten(el)
            else:
                yield el
    

    然后简单地创建一个新的列表理解,从每个 OrderedDict 中收集所有名称:

    print([d["name"] for d in flatten(list_of_interest)])
    # ['Viscozyme', 'Davictrel', 'Enbrel Sureclick', 'Tunex', 'Angiox', 'Enantone', 'Leuplin', 'LeuProMaxx', 'Leupromer', 'Lutrate', 'Memryte', 'Prostap 3', 'Prostap SR', 'Viadur', 'Geref']
    

    注意:yield from flatten(el) 语法等同于for x flatten(el): yield x。这只是 python 3 中可用的简洁语法。

    【讨论】:

      【解决方案4】:

      您必须遍历列表,然后递归到每个嵌套列表中

      def get_names(list_of_interest):
          names = []
          for d in list_of_interest:
              if ininstance(d, list):
                  names.extend(get_names(d))
              else:
                  names.append(d['name'])
          return names 
      

      【讨论】:

        【解决方案5】:

        采用我在 stackoverflow.com/a/9808122/1281485 中的回答,并将其调整为稍微不同的任务:

        def find(key, value):
          if isinstance(value, dict):
            for k, v in value.iteritems():
              if k == key:
                yield v
              else:
                for result in find(key, v):
                  yield result
          elif isinstance(value, list):
            for element in value:
              for result in find(key, element):
                yield result
        

        然后:

        print(list(find('name', list_of_interest)))
        

        【讨论】:

          【解决方案6】:

          另一个递归选项:

          def flat(lst, res = None):
            if res == None: res = []
            for item in lst:
              if not type(item) == list: res.append(item['name'])
              else: flat(item, res)
            return res
          
          print(flat(list_of_interest))
          #=> ['Viscozyme', 'Davictrel', 'Enbrel Sureclick', 'Tunex', 'Angiox', 'Enantone', 'Leuplin', 'LeuProMaxx', 'Leupromer', 'Lutrate', 'Memryte', 'Prostap 3', 'Prostap SR', 'Viadur', 'Geref']
          

          【讨论】:

            猜你喜欢
            • 2019-05-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-08-25
            • 1970-01-01
            • 2018-10-30
            • 2020-12-15
            相关资源
            最近更新 更多