Grammatically correct human readable string from list (with Oxford comma)

我的梦境 提交于 2019-12-06 08:00:56

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!