问题
I want a grammatically correct human-readable string representation of a list. For example, the list ['A', 2, None, 'B,B', 'C,C,C']
should return the string A, 2, None, B,B, and C,C,C
. This contrived example is somewhat necessary. Note that the Oxford comma is relevant for this question.
I tried ', '.join(seq)
but this doesn't produce the expected result for the aforementioned example.
Note the preexisting similar questions:
- How to print a list in Python "nicely" doesn't concern with a grammatically correct human-readable string.
- Grammatical List Join in Python is without the Oxford comma. The example and answers there are correspondingly different and they do not work for my question.
回答1:
This function works by handling small lists differently than larger lists.
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]
Usage examples:
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'
回答2:
You can also use unpacking for a slightly cleaner solution:
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])
Output:
['', 'A', 'A and 2', 'A, None, and C', 'A, B,B, and C,C,C', 'A, B, C, and D']
回答3:
I got really stubborn and I really wanted to figure out a one-liner solution.
"{} 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)))])
EDIT
I think this one does the trick. And I think the problem is also more complicated than I thought to be solved with a non-ugly one-liner.
回答4:
Based on the accepted answer for the thread you linked to, here's a one-liner that takes an optional argument for whether to use an Oxford comma or not.
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:])])
来源:https://stackoverflow.com/questions/53981845/grammatically-correct-human-readable-string-from-list-with-oxford-comma