Фильтрация понимания списка внутри другого понимания списка - PullRequest
1 голос
/ 05 марта 2020

Вот мой текущий код:

[[td.text.strip() for td in tr.find_all('td')] for tr in table.find_all('tr')]

По сути, я делаю парсинг выходных данных выбранной таблицы BeautifulSoup + Requests с веб-страницы. Независимо от цели, часть [td.text.strip() for td in tr.find_all('td')] дает мне список, представляющий строку, и она отлично работает. Однако я хотел бы отфильтровать этот список, чтобы удалить строки, где первый элемент - пустая строка. Итак, мой код превратился бы в

[[td.text.strip() for td in tr.find_all('td')] for tr in table.find_all('tr') if [td.text.strip() for td in tr.find_all('td')][0] != ""

, что печально и ужасно. Я пришел из опыта функционального программирования в Scala, поэтому использование операций map, filter и Reduce для меня вполне нормально, но в Python они возвращают map object вместо правильного списка, так что есть еще один List(map(lambda: ...)), который делает код действительно плохим с кучей скобок тут и там, при каждом вызове функции высокого порядка.

Есть ли способ Pythoni c, чтобы сделать это, при этом сохраняя читабельность? Я почти опускаюсь до простого .append(), чтобы сделать его читабельным, несмотря на то, что мне вообще не нужен pythoni c.

Редактировать: мне действительно нужен список списков, потому что я буду выполнять это много время, чтение нескольких таблиц, а затем, возможно, добавление их всех, поэтому, пожалуйста, не пытайтесь изменить эту часть структуры кода.

Редактировать 2: Это мой текущий нефильтрованный вывод. Моя цель - отфильтровать первые две строки.

[
 ['', '', '', ''],
 ['', '', 'Taxas de juros'],
 ['Posição', 'Instituição', '% a.m.', '% a.a.'],
 ['1', 'SINOSSERRA S/A - SCFI', '0,41', '5,03'],
 ['2', 'GRAZZIOTIN FINANCIADORA SA CFI', '0,84', '10,55'],
 ['3', 'BCO CATERPILLAR S.A.', '0,89', '11,27'],
 ['4', 'BCO VOLKSWAGEN S.A', '0,91', '11,49']
]

Ответы [ 2 ]

1 голос
/ 05 марта 2020

За 2 прохода было бы достаточно:

lst = [[td.text.strip() for td in tr.find_all('td')] for tr in table.find_all('tr')]
[i for i in lst if i[0] != '']

, чтобы получить:

[['Posição', 'Instituição', '% a.m.', '% a.a.'],
 ['1', 'SINOSSERRA S/A - SCFI', '0,41', '5,03'],
 ['2', 'GRAZZIOTIN FINANCIADORA SA CFI', '0,84', '10,55'],
 ['3', 'BCO CATERPILLAR S.A.', '0,89', '11,27'],
 ['4', 'BCO VOLKSWAGEN S.A', '0,91', '11,49']]

Вы можете сделать это за один проход таким образом:

[i for i in [[td.text.strip() for td in tr.find_all('td')]
             for tr in table.find_all('tr')] if i[0] != '']
1 голос
/ 05 марта 2020

Я бы сделал

[[td.text.strip() for td in tr.find_all('td')] 
 for tr in table.find_all('tr') 
 if tr.find('td').text.strip()]

Поскольку tr.find('td') вернет первого ребенка td. И урезанный текст этого будет либо иметь длину, либо не будет. А в Python строка длиной больше 0 оценивается как True.

...