Формирование массива из элементов в списке списков

1

Я пытаюсь создать массив из данных в списке списков.

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('')
Теги:
list
python-3.x
loops

7 ответов

2

Как я уже упоминал в комментарии, ваш блок else находится внутри вложенного цикла, что означает, что для всех элементов в каждом списке, если условие не выполняется, у вас будет пустая строка. Вы можете использовать флаг, чтобы узнать, выполняется if блок 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', '']

Но так как это не очень путинский способ решения проблемы, вместо этого вы можете использовать выражения генератора и next() функцию 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', ''])
  • 0
    Как бы я тогда включить цикл по именам столбцов. так что если col = ['ab', 'ac', 'db', 'dc', 'cg', 'pt', 'dd']? где это вписалось бы в петлю?
  • 0
    @ SnookerRogers Я не понимаю, как это связано с вашим вопросом и / или ожидаемым результатом?
1

Вы можете использовать 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]
1
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', '']
  • 0
    Это не создает пустую строку для последнего списка.
  • 0
    я обновляю это спасибо
Показать ещё 8 комментариев
0

Попробуй это:

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', ' ']
0

Есть много способов сделать это, как показали люди. Вот один из способов использования списков и функций более высокого порядка:

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]]
  • 0
    Благодарю. я должен освежить понимание списка
0

После некоторого озадачивания я нашел возможное решение

Обработайте каждый элемент в каждом подсписке индивидуально: если он содержит "ac", тогда разделите "ac =" часть. Если нет, просто верните пустую строку ''. Затем объедините все элементы в каждом подсписке, используя string.join(). Это вернет список строк с числовой строкой, например, "25" или пустой строкой. Наконец, условно преобразуйте каждую строку в целое число, если это возможно. Else просто возвращает (пустую) строку.

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, '']

edit: Если вы хотите расширить его до нескольких имен столбцов, например:

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]]
0

Это будет работать для любой длины 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)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню