Python: грамматически корректная читаемая человеком строка из списка (с оксфордской запятой)
Я хочу, чтобы грамматически правильное читаемое человеком строковое представление списка. Например, список ['A', 2, None, 'B,B', 'C,C,C']
должен вернуть строку A, 2, None, B,B, and C,C,C
, Этот надуманный пример несколько необходим. Обратите внимание, что оксфордская запятая имеет отношение к этому вопросу.
Я старался ', '.join(seq)
но это не дает ожидаемого результата для вышеупомянутого примера.
Обратите внимание на ранее существовавшие подобные вопросы:
- Как напечатать список в Python "красиво", не имеет отношения к грамматически правильной читаемой человеком строке.
- Грамматический список Регистрация в Python без запятой Оксфорд. Пример и ответы там соответственно разные, и они не работают для моего вопроса.
2 ответа
Эта функция работает. Маленькие списки обрабатываются по-разному.
from typing import Any, List
def readable_list(seq: List[Any]) -> str:
seq = [str(s) for s in seq]
if len(seq) < 3:
return ' and '.join(seq)
return ', '.join(seq[:-1]) + ', and ' + seq[-1]
Примеры использования:
readable_list([])
''
readable_list(['A'])
'A'
readable_list(['A', 2])
'A and 2'
readable_list(['A', None, 'C'])
'A, None, and C'
readable_list(['A', 'B,B', 'C,C,C'])
'A, B,B, and C,C,C'
readable_list(['A', 'B', 'C', 'D'])
'A, B, C, and D'
Вы также можете использовать распаковку для более чистого решения:
def readable_list(_s):
if len(_s) < 3:
return ' and '.join(map(str, _s))
*a, b = _s
return f"{', '.join(map(str, a))}, and {b}"
vals = [[], ['A'], ['A', 2], ['A', None, 'C'], ['A', 'B,B', 'C,C,C'], ['A', 'B', 'C', 'D']]
print([readable_list(i) for i in vals])
Выход:
['', 'A', 'A and 2', 'A, None, and C', 'A, B,B, and C,C,C', 'A, B, C, and D']
Я стал очень упрямым и очень хотел придумать однострочное решение.
"{} and {}".format(seq[0], seq[1]) if len(seq)==2 else ', '.join([str(x) if (y < len(seq)-1 or len(seq)<=1) else "and {}".format(str(x)) for x, y in zip(seq, range(len(seq)))])
ИЗМЕНИТЬ
Я думаю, что это трюк. И я думаю, что проблема еще сложнее, чем я думал, чтобы ее решить с помощью некрасивого однострочника.
Основываясь на принятом ответе для темы, с которой вы связались, вот однострочный текст, который принимает необязательный аргумент о том, использовать ли оксфордскую запятую или нет.
from typing import List
def list_items_in_english(l: List[str], oxford_comma: bool = True) -> str:
"""
Produce a list of the items formatted as they would be in an English sentence.
So one item returns just the item, passing two items returns "item1 and item2" and
three returns "item1, item2, and item3" with an optional Oxford comma.
"""
return ", ".join(l[:-2] + [((oxford_comma and len(l) != 2) * ',' + " and ").join(l[-2:])])