Is there an easy to "humanize" a list?

42 views
Skip to first unread message

Austin Govella

unread,
Dec 20, 2006, 8:27:11 AM12/20/06
to django...@googlegroups.com
I have a list from a queryset:
* foo
* bar
* twinky

Is there an easy way to output that as: "foo, bar, and twinky"

(There are handy functions for this in PHP, ColdFusion, and Rails, but
my Google-fu fails for Python or Django.)

Thanks,
--
Austin Govella
Thinking & Making: IA, UX, and IxD
http://thinkingandmaking.com
austin....@gmail.com

James Aylett

unread,
Dec 20, 2006, 9:12:08 AM12/20/06
to django...@googlegroups.com
On Wed, Dec 20, 2006 at 08:27:11AM -0500, Austin Govella wrote:

> I have a list from a queryset:
> * foo
> * bar
> * twinky
>
> Is there an easy way to output that as: "foo, bar, and twinky"

If you want to do it in python, use reduce:

----------------------------------------------------------------------
# l is the list, r is the humanised result
r = reduce(lambda x, y: str(x) + "," + str(y), l)
----------------------------------------------------------------------

or similar.

James

--
/--------------------------------------------------------------------------\
James Aylett xapian.org
ja...@tartarus.org uncertaintydivision.org

Jonathan Buchanan

unread,
Dec 20, 2006, 9:26:09 AM12/20/06
to django...@googlegroups.com
On 12/20/06, Austin Govella <austin....@gmail.com> wrote:
>
> I have a list from a queryset:
> * foo
> * bar
> * twinky
>
> Is there an easy way to output that as: "foo, bar, and twinky"
>
> (There are handy functions for this in PHP, ColdFusion, and Rails, but
> my Google-fu fails for Python or Django.)
>
>
>
> Thanks,
> --
> Austin Govella

http://www.djangoproject.com/documentation/templates/#join

{{ your_list|join:", " }}

Jonathan.

Fredrik Lundh

unread,
Dec 20, 2006, 9:30:02 AM12/20/06
to django...@googlegroups.com
James Aylett wrote:

>> Is there an easy way to output that as: "foo, bar, and twinky"
>
> If you want to do it in python, use reduce:
>
> ----------------------------------------------------------------------
> # l is the list, r is the humanised result
> r = reduce(lambda x, y: str(x) + "," + str(y), l)
> ----------------------------------------------------------------------

or more efficiently,

text = ", ".join(map(str, data))

but this only inserts commas. maybe you could add something like this
to a suitable templatetags module:

def join_en(seq):
seq = map(str, seq)
if not seq:
return "" # empty
if len(seq) == 1:
return seq[0]
elif len(seq) == 2:
return " and ".join(seq)
text = ", ".join(seq[:-1])
return text + ", and " + seq[-1]
register.filter(join_en)

tweak as necessary.

(note that there is a "humanize" template tag collection under contrib,
but that one is currently focussed on numbers, not lists).

</F>

Waylan Limberg

unread,
Dec 20, 2006, 11:27:51 AM12/20/06
to django...@googlegroups.com
On 12/20/06, Austin Govella <austin....@gmail.com> wrote:
>
> Is there an easy way to output that as: "foo, bar, and twinky"
>

Not that we need another way but this would work as well, and it
doesn't need special cases for one and two item lists but does insert
the "and" (unlike most of the solutions offered):

def humanize_list(list):
return ", and".join(map(str, ", ".join(map(str, list)).rsplit(',',1)))

--
----
Waylan Limberg
way...@gmail.com

Fredrik Lundh

unread,
Dec 20, 2006, 1:04:43 PM12/20/06
to django...@googlegroups.com
Waylan Limberg wrote:

> Not that we need another way but this would work as well, and it
> doesn't need special cases for one and two item lists but does insert
> the "and" (unlike most of the solutions offered):
>
> def humanize_list(list):
> return ", and".join(map(str, ", ".join(map(str, list)).rsplit(',',1)))

>>> humanize_list(["one", "two"])
'one, and two'

</F>

Brian Beck

unread,
Dec 20, 2006, 1:56:42 PM12/20/06
to Django users
from django.utils.text import get_text_list

Fredrik Lundh

unread,
Dec 20, 2006, 2:04:10 PM12/20/06
to django...@googlegroups.com
Brian Beck wrote:

> from django.utils.text import get_text_list

doesn't match the OP's specification for all lists, though:

>>> get_text_list(["one", "two", "three"], 'and')
'one, two and three'

but I guess you could always do

if len(seq) >= 2:
text = get_text_list(seq, ", and")
else:
text = get_text_list(seq, "and")

</F>

James Bennett

unread,
Dec 20, 2006, 3:49:01 PM12/20/06
to django...@googlegroups.com
On 12/20/06, Austin Govella <austin....@gmail.com> wrote:
> Is there an easy way to output that as: "foo, bar, and twinky"
>
> (There are handy functions for this in PHP, ColdFusion, and Rails, but
> my Google-fu fails for Python or Django.)

As far as template logic is concerned, I do something similar on my
blog to list the categories each post is in; I just use the {% for %}
tag to loop over the list of categories, and added a couple checks to
determine whether to put a comma after each one and where to put the
'and' (using tests for 'forloop.last' within the loop).

--
"May the forces of evil become confused on the way to your house."
-- George Carlin

Waylan Limberg

unread,
Dec 20, 2006, 4:53:57 PM12/20/06
to django...@googlegroups.com
Ahh, right, when I whipped that up, I wasn't including a comma with
the and, but before posting I reread the original email and saw the
comma was included in the request so I just stuck it in there without
further testing. Personally, I would just pull that comma out (the
first comma in line 2), which gives us the same result as
django.utils.text.get_text_list.
Reply all
Reply to author
Forward
0 new messages