Simon S
Simon S

Reputation: 303

Converting a list into comma-separated string with "and" before the last item - Python 2.7

I have created this function to parse the list:

listy = ['item1', 'item2','item3','item4','item5', 'item6']


def coma(abc):
    for i in abc[0:-1]:
        print i+',',
    print "and " + abc[-1] + '.'

coma(listy)

#item1, item2, item3, item4, item5, and item6.

Is there a neater way to achieve this? This should be applicable to lists with any length.

Upvotes: 18

Views: 6319

Answers (10)

UltraInstinct
UltraInstinct

Reputation: 44444

When there are 1+ items in the list (if not, just use the first element):

>>> "{} and {}".format(", ".join(listy[:-1]),  listy[-1])
'item1, item2, item3, item4, item5 and item6'

Edit: If you need an Oxford comma (didn't know it even existed!) -- just use: ", and" instead:

>>> "{}, and {}".format(", ".join(listy[:-1]),  listy[-1])
'item1, item2, item3, item4, item5, and item6'

Upvotes: 30

robbyoconnor
robbyoconnor

Reputation: 151

I cannot take full credit but if you want succinct -- I modified RoadieRich's answer to use f-strings and also made it more concise. It uses the solution by RootTwo given in a comment on that answer:

def join(items):
    *start, last = items
    return f"{','.join(start)}, and {last}" if start else last

Upvotes: 2

snoopyjc
snoopyjc

Reputation: 623

Correction for Craig’s answer above for a 2-element list (I’m not allowed to comment):

def oxford_comma_join(l):
    if not l:
        return ""
    elif len(l) == 1:
        return l[0]
    elif len(l) == 2:
        return l[0] + " and " + l[1]
    else:
        return ', '.join(l[:-1]) + ", and " + l[-1]

print(oxford_comma_join(['item1', 'item2', 'item3', 'item4', 'item5', 'item6']))

print(oxford_comma_join(['i1', 'i2']))

Results:

item1, item2, item3, item4, item5, and item6
i1 and i2

Upvotes: 3

mark
mark

Reputation: 5070

You can also try the quoter library

>>> import quoter
>>> mylist = ['a', 'b', 'c']
>>> quoter.and_join(mylist)
'a, b, and c'
>>> quoter.or_join(mylist)
'a, b, or c'

https://pypi.python.org/pypi/quoter

Upvotes: 0

Sunil Kapil
Sunil Kapil

Reputation: 1040

One more different way to do:

listy = ['item1', 'item2','item3','item4','item5', 'item6']

first way:

print(', '.join('and, ' + listy[item] if item == len(listy)-1 else listy[item]
for item in xrange(len(listy))))

output >>> item1, item2, item3, item4, item5, and, item6

second way:

print(', '.join(item for item in listy[:-1]), 'and', listy[-1])

output >>> (item1, item2, item3, item4, item5, 'and', 'item6')

Upvotes: 2

wwii
wwii

Reputation: 23753

Might as well round out the solutions with a recursive example.

>>> listy = ['item1', 'item2','item3','item4','item5', 'item6']
>>> def foo(a):
    if len(a) == 1:
        return ', and ' + a[0]
    return a[0] + ', ' + foo(a[1:])

>>> foo(listy)
'item1, item2, item3, item4, item5, , and item6'
>>> 

Upvotes: 1

Daniel
Daniel

Reputation: 42748

In python, many functions, that work with lists also works with iterators (like join, sum, list). To get the last item of a iterable is not that easy, because you cannot get the length, because it may be unknown in advance.

def coma_iter(iterable):
    sep = ''
    last = None
    for next in iterable:
        if last is not None:
            yield sep
            yield last
            sep = ', '
        last = next
    if sep:
        yield ', and '
    if last is not None:
        yield last

print ''.join(coma_iter(listy))

Upvotes: 1

RoadieRich
RoadieRich

Reputation: 6566

It's generally bad practice to use + when combining strings, as it is generally slow. Instead, you can use

def comma(items):
    return "{}, and {}".format(", ".join(items[:-1]), items[-1])

You should note, however, that this will break if you only have one item:

>>> comma(["spam"])
', and spam'

To solve that, you can either test the length of the list (if len(items) >= 2:), or do this, which (imho) is slightly more pythonic:

def comma(items):
    start, last = items[:-1], items[-1]

    if start:
        return "{}, and {}".format(", ".join(start), last)
    else:
        return last

As we saw above, a single item list will result in an empty value for items[:-1]. if last: is just a pythonic way of checking if last is empty.

Upvotes: 1

Craig Burgler
Craig Burgler

Reputation: 1779

def oxford_comma_join(l):
    if not l:
        return ""
    elif len(l) == 1:
        return l[0]
    else:
        return ', '.join(l[:-1]) + ", and " + l[-1]

print(oxford_comma_join(['item1', 'item2', 'item3', 'item4', 'item5', 'item6']))

Output:

item1, item2, item3, item4, item5, and item6

Also as an aside the Pythonic way to write

for i in abc[0:-1]:

is

for i in abc[:-1]:

Upvotes: 7

Timofey Stolbov
Timofey Stolbov

Reputation: 4621

def coma(lst):
    return '{} and {}'.format(', '.join(lst[:-1]), lst[-1])

Upvotes: 4

Related Questions