Выражение присваивания Python 3.8 в понимании списка

Я пытаюсь использовать новое выражение присваивания для в первый раз и мог бы использовать некоторую помощь.

Учитывая три строки выходных данных журнала:

sin = """Writing 93 records to /data/newstates-900.03-07_07/top100.newstates-900.03-07_07/Russia.seirdc.March6-900.12.csv ..
Writing 100 records to /data/newstates-900.03-07_07/top100.newstates-900.03-07_07/India.seirdc.March6-900.6.csv ..
Writing 100 records to /data/newstates-900.03-07_07/top100.newstates-900.03-07_07/US.seirdc.March6-900.15.csv ..
"""

Цель состоит в том, чтобы извлечь только State (Россия, Индия и США) и количество записей (93 100 100) . Итак, желаемый результат:

[['Russia',93],['India',100],['US',100]]

Для этого необходимо выполнить следующие шаги для перевода на Python:

  • Преобразуйте каждую строку в элемент списка
  • Разделить по пробелу, например. ['Writing', '93', 'records', 'to', '/data/newstates-900.03-07_07/top100.newstates-900.03-07_07/Russia.seirdc.March6-900.12.csv', '..']
  • Разделите пятый такой токен на «/» и сохраните последний элемент: например. Russia.seirdc.March6-900.12.csv
  • Разделите этот элемент на '.' и сохраните первый (0-й) элемент, например. Russia

Вот моя неправильная попытка:

import fileinput
y = [[ z[4].split('/')[-1].split('.')[0],z[1]] 
     for (z:=x.split(' ')) in 
     (x:=sin if sin else fileinput.input()).splitlines())]

person WestCoastProjects    schedule 09.03.2020    source источник


Ответы (3)


Достаточно ли этого?

[[(wrds := line.split())[4].split("/")[-1].split('.')[0], wrds[1]] for line in sin.splitlines()]

Я считаю использование выражения присваивания избыточным. Вы также можете сделать это:

[[line.split('/')[-1].split('.')[0], line.split()[1]] for line in sin.splitlines()]
person ori6151    schedule 09.03.2020
comment
Присвоение не является лишним: ваш второй выполняет split() дважды. Представьте, если бы это была дорогая операция. Я награждаю, потому что это хороший ответ. На самом деле второй вариант довольно умный, но также и обманный: он использует «/», существующий только в последнем токене, разделенном пробелом. - person WestCoastProjects; 09.03.2020
comment
@javadba Я согласен с вами, но я имел в виду именно эту конкретную проблему. Также, если мой ответ - это то, что вы искали, вы можете поставить галочку рядом с моим ответом. Спасибо :) - person ori6151; 09.03.2020
comment
Если у вас есть шанс: я действительно хотел бы увидеть двойную вложенную структуру. Подумайте о том, чтобы не использовать трюк, чтобы свернуть это в один уровень: т. Е. OP - это игрушечный пример, но цель состоит в том, чтобы понять, как выполнять несколько уровней вложенности (где многоуровневые уровни действительно необходимы) и с выражением присваивания. - person WestCoastProjects; 09.03.2020
comment
re: дважды вложенная структура. Вы можете подождать с этим: я собираюсь создать отдельный вопрос, в котором не будет возможно раздавить уровни. Он будет включать операции группировки и агрегирования числовых данных. - person WestCoastProjects; 09.03.2020

Что бы это ни стоило, вы также можете получить это с помощью регулярного выражения, что, вероятно, было бы более предпочтительным/эффективным.

[list(reversed(l)) for l in re.findall(r'Writing (\d+).+\/([A-Z,a-z]+)\.', sin)]

Или, точнее, (для преобразования int) и для удобочитаемости (согласно @chepner в комментариях):

[[country, int(count)] for count, country in re.findall(r'Writing (\d+).+\/([A-Z,a-z]+)\.', sin)]
person Jab    schedule 09.03.2020
comment
[ [country, int(count)] for count, country in ... ] было бы более читаемым (и лучше соответствовало бы запрошенному выводу). - person chepner; 09.03.2020
comment
Полезный подход. Я действительно хочу использовать walrus для многих других задач обработки данных, которые не поддаются умной эвристике: но особенно для разбора тестов по-вашему имеет смысл. Добавление @chepner также полезно. - person WestCoastProjects; 09.03.2020
comment
О, вы только что удалили reverse(list). Я думаю, что это также полезно упомянуть (а не просто полностью потерять) - person WestCoastProjects; 09.03.2020
comment
Я удалил реверс, так как он более читабелен и упрощает преобразование счетчика в int. - person Jab; 09.03.2020
comment
Да, я понял, но трюк с reverse() на самом деле является дополнительным, который нужно сохранить в наборе инструментов. Что ж, я уже усвоил это, но будущие читатели увидят конечный продукт, а не то (интересное) промежуточное решение. - person WestCoastProjects; 09.03.2020

Вот один из способов:

results = []
for line in sin.split('..'):
    if len(z := line.split(' ')) > 1 :
        results.append([line.split('/')[-1].split('.')[0], z[1]])
person David Diamond    schedule 09.03.2020
comment
Пожалуйста, смотрите выше: принятый ответ использует его в понимании for. Вы также можете обратиться к связанным документам PEP. - person WestCoastProjects; 09.03.2020