【问题标题】:Forming an array from items in list of lists从列表列表中的项目形成数组
【发布时间】:2018-06-16 07:57:23
【问题描述】:

我正在尝试从列表列表中的数据创建一个数组。

ac_name = 'ac'
dat = [['ab=55', 'ac=25', 'db =57', 'dc =44'],
       ['ab=75','ac =12', 'cg =11', 'pt =95'],
       ['ab=17', 'ac=62'],
       ['ab=97', 'aa=501', 'dc=12', 'dd=19']]

所以我想得到一个看起来像这样的列表

ac = ['ac=25','ac=12','ac=62','']

从这里得到

ac_values = [25,12,62,'']

总而言之,我想将 dat 转换为一个大数组。

我知道这不起作用,因为它会遍历每个项目,因此输出是 dat 中有多少元素。

ac = []
for d in dat:
    for c in d:
        if ac_name in c:
            ac.append(c)
        else:
            ac.append('')

【问题讨论】:

  • 您的 else 块位于嵌套循环内,这意味着如果条件未执行,对于每个列表中的所有项目,您将有一个空字符串。
  • 如果子列表中有多个'ac='怎么办?
  • @Kasramvd 非常感谢。我以前没见过
  • “数组”是什么意思?一个numpy.array?一个array.array?通常一个python数组只能有一种数据类型,不能组合字符串和整数...

标签: python python-3.x list loops


【解决方案1】:

正如我在评论中提到的,您的 else 块位于嵌套循环内,这意味着对于每个列表中的所有项目,如果条件未执行,您将有一个空字符串。您可以使用标志来查看if 块是否在嵌套循环中执行,并在最终结果中附加一个空字符串。

In [6]: ac = []
   ...: for d in dat:
   ...:     flag = True
   ...:     for c in d:
   ...:         if ac_name in c:
   ...:             ac.append(c)
   ...:             flag = False
   ...:     if flag:
   ...:         ac.append('')
   ...:         

In [7]: ac
Out[7]: ['ac=25', 'ac =12', 'ac=62', '']

但是,由于这不是处理问题的 Pythonic 方式,因此您可以使用生成器表达式和 next() 函数,如下所示,根据预期结果创建字典。在这种情况下,您也可以轻松访问键或值。

In [19]: result = dict((ind, next((i for i in d if i.startswith(ac_name)), '=').split('=')[1]) for ind, d in enumerate(dat))

In [20]: result
Out[20]: {0: '25', 1: '12', 2: '62', 3: ''}

In [21]: result.keys() # shows number of sub-lists in your original list
Out[21]: dict_keys([0, 1, 2, 3])

In [22]: result.values()
Out[22]: dict_values(['25', '12', '62', ''])

【讨论】:

  • 我将如何在列名中加入循环。所以如果 col = ['ab','ac','db','dc','cg','pt','dd'] ?这将在哪里适合循环?
  • @SnookerRogers 我看不出这与您的问题和/或您的预期输出有何关系?
【解决方案2】:
ac_name = 'ac'
datas = [['ab=55', 'ac=25', 'db =57', 'dc =44'],
    ['ab=75','ac =12', 'cg =11', 'pt =95'],
    ['ab=17', 'ac=62'],
    ['ab=97', 'aa=501', 'dc=12', 'dd=19'],
    ['ab=55', 'ac=25', 'db =57', 'dc =44'],
    ['ab=75','ac =12', 'cg =11', 'pt =95'],
    ['ab=17', 'ac=62'],
    ['ab=97', 'aa=501', 'dc=12', 'dd=19']]

lst = []

for i,data in enumerate(datas):
    for d in data:
        if ac_name in d:
            lst.append(d.split('=')[-1])
    if i == len(lst):
        lst.append('')

print(lst)

输出

['25', '12', '62', '', '25', '12', '62', '']

【讨论】:

  • 这不会为最后一个列表生成空字符串。
  • 嘿@zimdero 很高兴再次看到您的答案。很好的解决方案。
  • 我认为如果datas 中有更多项目在没有ac 的项目之后,这将不起作用。
  • @zimdero 谢谢。然后我将如何在列名中加入循环。所以如果 col = ['ab','ac','db','dc','cg','pt','dd'] ?
  • 你想说,而不是ac_name = 'ac',你想搜索col = ['ab', 'ac']
【解决方案3】:

您可以使用itertools.chain 来展平您的列表列表。然后根据需要使用列表推导来过滤和拆分元素。

from itertools import chain

res = [int(i.split('=')[-1]) for i in chain.from_iterable(dat) \
       if i.startswith('ac')]

print(res)

[25, 12, 62]

【讨论】:

    【解决方案4】:

    正如人们所展示的,有很多方法可以做到这一点。这是使用列表推导和高阶函数的一种方法:

    In [14]: ["" if not kv else kv[0].split('=')[-1].strip() for kv in  [filter(lambda x: x.startswith(ac_name), xs) for xs in datas]]
    Out[14]: ['25', '12', '62', '']
    

    如果需要精确的键“ac”,也可以使用正则表达式:

    import re
    p = re.compile(ac_name + '\s*')
    ["" if not kv else kv[0].split('=')[-1].strip() for kv in  [filter(lambda x: p.match(x), xs) for xs in datas]]
    

    【讨论】:

      【解决方案5】:

      经过一番困惑,我找到了一个可能的解决方案

      单独处理每个子列表中的每个元素:如果它包含“ac”,则去掉“ac=”部分。如果没有,只返回一个空字符串''。 然后使用 string.join() 连接每个子列表中的所有元素。这将返回带有数字字符串的字符串列表,例如'25' 或空字符串。 最后,如果可能,有条件地将每个字符串转换为整数。否则只返回(空)字符串。

      ac = [int(cell_string) if cell_string.isdigit() else cell_string for cell_string in
            [''.join([cell.split('=')[1] if ac_name in cell else '' for cell in row]) for row in data]]
      

      输出:

      [25, 12, 62, '']
      

      编辑: 如果您想将其扩展到多个列名,例如:

      col_name = ['ac', 'dc']
      

      然后扩展这个:

      cols = [[int(cell_string) if cell_string.isdigit() else cell_string for cell_string in
               [''.join([cell.split('=')[1] if name in cell else '' for cell in row]) for row in data]] for name in col_name]
      

      输出:

      [[25, 12, 62, ''], [44, '', '', 12]]
      

      【讨论】:

        【解决方案6】:

        试试这个:

        ac_name = 'ac'
        ac = []
        ac_values = []
        
        for value in dat:
            found = False
            for item in value:
                if ac_name in item:
                    ac.append(item)
                    ac_values.append(item.split('=')[-1])
                    found = True
            if not found:
                ac.append(' ')
                ac_values.append(' ')
        
        print(ac)
        print(ac_values)
        

        输出:

        ['ac= 25', 'ac = 12', 'ac=62', ' ']
        [' 25', ' 12', '62', ' ']
        

        【讨论】:

          【解决方案7】:

          这适用于任何长度的ac_name

          ac_name = 'ac'
          ac = []
          ac_values=[]
          for i in dat:
              found=False
              for j in i:
                  if j[:2]==ac_name:
                      ac.append(j)
                      ac_values.append(int(j[len(ac_name)+2:]))
                      found=True
              if not found:
                  ac.append("")
                  ac_values.append("")
          print(ac)
          print(ac_values)
          

          【讨论】:

            猜你喜欢
            • 2021-03-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-06-12
            相关资源
            最近更新 更多