views:

109

answers:

5

I've got an array listing days of the week:

days = ['Monday', 'Tuesday', 'Wednesday']

Whats the easiest / best way to output it in a human readable format:

Monday, Tuesday and Wednesday

The best I have is a rather ugly:

', '.join(days[:-2]+['']) + ' and '.join(days[-2:])
A: 

One example, from Supybot

wRAR
+6  A: 

Here is what I would do:

'%s and %s' % (', '.join(days[:-1]), days[-1])

Not sure its pretty, but not sure it has to be either. :)

Randy Syring
Its good, but what if days is just ['Monday'] ?
Ross
@Ross: A more general but uglier solution would be: `(days + [''])[0] if len(days) <= 1 else '%s and %s' % (', '.join(days[:-1]), days[-1])`.
Max Shawabkeh
I giggle when I see a wrong answer with five votes.
Glenn Maynard
@Glenn Maynard: your answer below is a more holistic solution. I wasn't implying that my answer would work for every list, just a "better" way of writing the single expression he used above given the fixed list that was part of his question.@Ross: you want to use what I wrote as part of a function which takes into consideration the edge case of a single element list. Glenn's function is a good example.
Randy Syring
A: 

you really don't need that second join() in your 'best' sample. you can rewrite it this way:

', '.join(days[:-1])+' and '+days[-1]

personally, i always prefer calling the class method, because i find the syntax closer to the intent:

str.join(', ',days[:-1])+' and '+days[-1]
Adrien Plisson
A: 

I would make a lambda/function once and then just re-use it.

def days(*d):
    ''.join([i + ((n < len(d) - 2 and ', ') or ' and ') for n, i in enumerate(d)])[:-5] + '.'

print days('Monday', 'Tuesday', 'Wednesday')
>>> Monday, Tuesday and Wednesday.

print days('Monday', 'Tuesday')
>>> Monday and Tuesday.

print days('Monday', 'Tuesday')
>>> Monday.

Works for every combination too :)

Ivo Wetzel
You know, if a lambda gets as long as that, it probably makes sense to make it a normal function instead.
Max Shawabkeh
I know... but my there isn't much left over form my brain at this moment... to much coding today...
Ivo Wetzel
+2  A: 

Why is everyone trying to force-fit this into a single expression?

def comma_separated(lst):
    """
    >>> comma_separated(['a'])
    'a'
    >>> comma_separated(['a', 'b'])
    'a and b'
    >>> comma_separated(['a', 'b', 'c'])
    'a, b and c'
    """
    if len(lst) == 1:
        return lst[0]
    comma_part = ", ".join(lst[:-1])
    return "%s and %s" % (comma_part, lst[-1])

if __name__ == "__main__":
    import doctest
    doctest.testmod()

And remember, this is specific to English (and aside from "and", probably some other Western languages). Other languages have entirely different rules.

Glenn Maynard
I think my ugly example is the one that would pass code golf but I like this one as it seems the most pythonic / explicit compared to the others.
Ross