Velocity Reviews > counting items

# counting items

It's me
Guest
Posts: n/a

 01-12-2005
Okay, I give up.

What's the best way to count number of items in a list?

For instance,

a=[[1,2,4],4,5,[2,3]]

I want to know how many items are there in a (answer should be 7 - I don't
want it to be 4)

I tried:

b=len([x for y in a for x in y])

That doesn't work because you would get an iteration over non-sequence.

I tried:

g=lambda x: (1,len(x))[isinstance(x,(list,tuple,dict))]
b=sum(lambda(x) for x in a)

and that didn't work because I get a TypeError from the len function (don't
know why)

I can, of course:

i=0
for x in a:
if isinstance(x,(list,tuple,dict)):
i += len(x)
else:
i += 1

but that's so C-like...

Thanks,

Andrew Koenig
Guest
Posts: n/a

 01-12-2005
"It's me" <(E-Mail Removed)> wrote in message
news:ukdFd.10645\$(E-Mail Removed) m...

> What's the best way to count number of items in a list?
>
> For instance,
>
> a=[[1,2,4],4,5,[2,3]]
>
> I want to know how many items are there in a (answer should be 7 - I don't
> want it to be 4)

def totallen(x):
if isinstance(x, (list, tuple, dict)):
return sum(map(totallen, x))
return 1

Paul McGuire
Guest
Posts: n/a

 01-12-2005
"It's me" <(E-Mail Removed)> wrote in message
news:ukdFd.10645\$(E-Mail Removed) m...
> Okay, I give up.
>
> What's the best way to count number of items in a list?
>
> For instance,
>
> a=[[1,2,4],4,5,[2,3]]
>
> I want to know how many items are there in a (answer should be 7 - I don't
> want it to be 4)
>

<snip>

I've sure seen a lot of questions about the flattening of lists. I found
this version of flatten somewhere, I thought I got it from the Python
Cookbook but I can't find it now. Perhaps it was posted here on c.l.py. I
*don't* claim authorship, I'm merely an admirer of such a clean-looking
solution.

def flatten(a):
if not isinstance(a, (tuple,list)): return [a]
if len(a)==0: return []
return flatten(a[0])+flatten(a[1:])

a = [[1, 2, 4], 4, 5, [2, 3], 6, [6], [], 'askjdf']

print len(flatten(a))

gives the value 10.

Considering how often this comes up, might there be a place for some sort of
flatten() routine in the std dist, perhaps itertools?

-- Paul

Mark McEahern
Guest
Posts: n/a

 01-12-2005
It's me wrote:

>Okay, I give up.
>
>What's the best way to count number of items in a list [that may contain lists]?
>
>

a = [[1,2,4],4,5,[2,3]]

def iterall(seq):
for item in seq:
try:
for subitem in iterall(item):
yield subitem
except TypeError:
yield item

all = [x for x in iterall(a)]
print len(all)

It's me
Guest
Posts: n/a

 01-12-2005
Thanks.

May be flatten should be build into the language somehow....

"Paul McGuire" <(E-Mail Removed)._bogus_.com> wrote in message
news:aKdFd.8991\$(E-Mail Removed)...
> "It's me" <(E-Mail Removed)> wrote in message
> news:ukdFd.10645\$(E-Mail Removed) m...
> > Okay, I give up.
> >
> > What's the best way to count number of items in a list?
> >
> > For instance,
> >
> > a=[[1,2,4],4,5,[2,3]]
> >
> > I want to know how many items are there in a (answer should be 7 - I

don't
> > want it to be 4)
> >

> <snip>
>
> I've sure seen a lot of questions about the flattening of lists. I found
> this version of flatten somewhere, I thought I got it from the Python
> Cookbook but I can't find it now. Perhaps it was posted here on c.l.py.

I
> *don't* claim authorship, I'm merely an admirer of such a clean-looking
> solution.
>
> def flatten(a):
> if not isinstance(a, (tuple,list)): return [a]
> if len(a)==0: return []
> return flatten(a[0])+flatten(a[1:])
>
> a = [[1, 2, 4], 4, 5, [2, 3], 6, [6], [], 'askjdf']
>
> print len(flatten(a))
>
> gives the value 10.
>
> Considering how often this comes up, might there be a place for some sort

of
> flatten() routine in the std dist, perhaps itertools?
>
> -- Paul
>
>

It's me
Guest
Posts: n/a

 01-12-2005
Oh, darn. I asked this kind of question before. <plonk, plonk>

def flatten(seq):
for x in seq:
if hasattr(x, "__iter__"):
for subx in flatten(x):
yield subx
else:
yield x

data = [[1,5,2],8,4]
val_to_pos = {}
for i, x in enumerate(flatten(data)):
val_to_pos[x] = i + 1
print val_to_pos

"It's me" <(E-Mail Removed)> wrote in message
news:ukdFd.10645\$(E-Mail Removed) m...
> Okay, I give up.
>
> What's the best way to count number of items in a list?
>
> For instance,
>
> a=[[1,2,4],4,5,[2,3]]
>
> I want to know how many items are there in a (answer should be 7 - I don't
> want it to be 4)
>
> I tried:
>
> b=len([x for y in a for x in y])
>
> That doesn't work because you would get an iteration over non-sequence.
>
> I tried:
>
> g=lambda x: (1,len(x))[isinstance(x,(list,tuple,dict))]
> b=sum(lambda(x) for x in a)
>
> and that didn't work because I get a TypeError from the len function

(don't
> know why)
>
> I can, of course:
>
> i=0
> for x in a:
> if isinstance(x,(list,tuple,dict)):
> i += len(x)
> else:
> i += 1
>
> but that's so C-like...
>
> Thanks,
>
>

Anthony
Guest
Posts: n/a

 01-12-2005
On Wed, 12 Jan 2005 17:42:50 GMT, It's me <(E-Mail Removed)> wrote:
> Okay, I give up.
>
> What's the best way to count number of items in a list?

How long is a piece of string? There are many different ways, which

> For instance,
>
> a=[[1,2,4],4,5,[2,3]]
>
> I want to know how many items are there in a (answer should be 7 - I don't
> want it to be 4)
>
> I tried:
>
> b=len([x for y in a for x in y])
>
> That doesn't work because you would get an iteration over non-sequence.

> I tried:
>
> g=lambda x: (1,len(x))[isinstance(x,(list,tuple,dict))]
> b=sum(lambda(x) for x in a)
>
> and that didn't work because I get a TypeError from the len function (don't
> know why)

Because you're trying to get the length of an integer, which is what's failing.

If you know that the list nesting is only one deep, you can do something like:

===
#!/usr/local/bin/python

compoundList = [[1,2,4],4,5,[2,3]]

listLengths = [len(item) for item in compoundList if type(item) not in
[int,long,str,float]]
print listLengths

compoundLength = len(compoundList) - len(listLengths) + sum(listLengths)
print compoundLength
===

If the nesting is 2 deep or more, then the next two options that I
would explore would be:

1. Have a look in the standard library. I'm pretty sure that there are
list-manipulation libraries that'll do what you want (not sure on
names, though).
2. Write a function to do what you want. Some sort of recursive thing
should be pretty easy to write. Of course it depends on how fast you
need to go, but that should give you a good first approximation.

Anthony

--
-----------------------------------------------------
HyPEraCtiVE? HeY, WhO aRE YoU cALliNg HypERaCtIve?!
http://www.velocityreviews.com/forums/(E-Mail Removed)
-----------------------------------------------------

It's me
Guest
Posts: n/a

 01-12-2005
Yes, Mark, I came up with almost the same code (after reading back old

def flatten(seq):
for x in seq:
if hasattr(x, "__iter__"):
for subx in flatten(x):
yield subx
else:
yield x

def count_item(data):
return len([(i,x) for i, x in enumerate(flatten(data))])

data = [[1,5,2],8,4]
print count_item(data)

Thanks everybody.

"Mark McEahern" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> It's me wrote:
>
> >Okay, I give up.
> >
> >What's the best way to count number of items in a list [that may contain

lists]?
> >
> >

> a = [[1,2,4],4,5,[2,3]]
>
> def iterall(seq):
> for item in seq:
> try:
> for subitem in iterall(item):
> yield subitem
> except TypeError:
> yield item
>
> all = [x for x in iterall(a)]
> print len(all)
>

Steven Bethard
Guest
Posts: n/a

 01-12-2005
Mark McEahern wrote:
> It's me wrote:
>
>> Okay, I give up.
>>
>> What's the best way to count number of items in a list [that may
>> contain lists]?
>>
>>

> a = [[1,2,4],4,5,[2,3]]
>
> def iterall(seq):
> for item in seq:
> try:
> for subitem in iterall(item):
> yield subitem
> except TypeError:
> yield item
>
> all = [x for x in iterall(a)]
> print len(all)
>

Beware:

py> list(iterall(['a']))
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
File "<interactive input>", line 4, in iterall
...
File "<interactive input>", line 4, in iterall
RuntimeError: maximum recursion depth exceeded

You need to special-case strings. I would do this explicitly, e.g.:

py> def iterall(seq):
.... for item in seq:
.... if isinstance(item, basestring):
.... yield item
.... else:
.... try:
.... for subitem in iterall(item):
.... yield subitem
.... except TypeError:
.... yield item
....
py> list(iterall(['a']))
['a']

but you can also do this by checking for __iter__ as in one of the other
posted solutions. (This takes advantage of the fact that strings use
the __getitem__ protocol for iteration instead of __iter__.)

Steve

Bernhard Herzog
Guest
Posts: n/a

 01-12-2005
"It's me" <(E-Mail Removed)> writes:

> May be flatten should be build into the language somehow....

That shouldn't be necessary as it can easily be written in a single list
comprehension:

a = [[1,2,4],4,5,[2,3]]
flat_a = [x for cur, rest in [[a[:1], a[1:]]] for x in cur
if (not isinstance(x, (list, tuple))
and (not rest or not cur.append(rest.pop(0)))
or (x and (cur.append(x[0]) or rest.__setslice__(0, 0, x[1:])))
or (not x and rest and cur.append(rest.pop(0))))]

Bernhard

--
Intevation GmbH http://intevation.de/
Skencil http://skencil.org/
Thuban http://thuban.intevation.org/