counting items

Discussion in 'Python' started by It's me, Jan 12, 2005.

  1. It's me

    It's me Guest

    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,
     
    It's me, Jan 12, 2005
    #1
    1. Advertising

  2. "It's me" <> wrote in message
    news:ukdFd.10645$...

    > 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)


    How about this?

    def totallen(x):
    if isinstance(x, (list, tuple, dict)):
    return sum(map(totallen, x))
    return 1
     
    Andrew Koenig, Jan 12, 2005
    #2
    1. Advertising

  3. It's me

    Paul McGuire Guest

    "It's me" <> wrote in message
    news:ukdFd.10645$...
    > 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
     
    Paul McGuire, Jan 12, 2005
    #3
  4. 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)
     
    Mark McEahern, Jan 12, 2005
    #4
  5. It's me

    It's me Guest

    Thanks.

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


    "Paul McGuire" <._bogus_.com> wrote in message
    news:aKdFd.8991$...
    > "It's me" <> wrote in message
    > news:ukdFd.10645$...
    > > 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, Jan 12, 2005
    #5
  6. It's me

    It's me Guest

    Oh, darn. I asked this kind of question before. <plonk, plonk>

    Somebody posted an answer before:

    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" <> wrote in message
    news:ukdFd.10645$...
    > 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,
    >
    >
     
    It's me, Jan 12, 2005
    #6
  7. It's me

    Anthony Guest

    On Wed, 12 Jan 2005 17:42:50 GMT, It's me <> 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
    give you different trade offs.

    > 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.


    And is very unreadable.

    > 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?!

    -----------------------------------------------------
     
    Anthony, Jan 12, 2005
    #7
  8. It's me

    It's me Guest

    Yes, Mark, I came up with almost the same code (after reading back old
    answers from this list):

    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" <> wrote in message
    news:...
    > 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, Jan 12, 2005
    #8
  9. 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
     
    Steven Bethard, Jan 12, 2005
    #9
  10. "It's me" <> 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/
     
    Bernhard Herzog, Jan 12, 2005
    #10
  11. There's a great function called "walk" at that iterates over arbitrary
    data (and is recursion-proof) at

    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/118845

    It also supplies a recursion-proof way to flatten a list. (Once you
    can iterate over an arbitrary sequence, the flattened version is just
    [element for element in walk(sequence)].) I use both functions all the
    time.

    Adding a flatten function (along with walk) to Python sounds like a
    good idea to me. Having used Mathematica for many years, which uses
    Flatten[] all over the place, I was actually quite surprised to find
    that Python didn't have it.

    Michael
     
    Michael Hartl, Jan 12, 2005
    #11
  12. Paul McGuire wrote:
    > Considering how often this comes up, might there be a place for some sort of
    > flatten() routine in the std dist, perhaps itertools?


    A problem I see is that itertools tries to work across all iterable
    types, but flattening can't always be a generalized operation. For
    instance, a naive flattening function might turn the list ['foo', 'bar']
    into ['f', 'o', 'o', 'b', 'a', 'r'] -- or worse, fall into infinite
    recursion -- when the intended result would be to leave the list
    unchanged. Of course, a generalized flattening function could take an
    argument listing types to ignore, but that can get very complicated very
    fast.
     
    Leif K-Brooks, Jan 12, 2005
    #12
  13. Michael Hartl wrote:
    > (Once you can iterate over an arbitrary sequence, the
    > flattened version is just
    > [element for element in walk(sequence)].)


    Or, better yet:

    list(walk(sequence))

    Steve
     
    Steven Bethard, Jan 12, 2005
    #13
  14. That's cool! Of course, walk returns a generator, so using a list
    comprehension to turn it into a list seems natural, but I didn't
    realize that list() does the same thing (and neither, apparently, did
    the original implementor) -- although, with a little reflection, it
    obviously must!

    Michael
     
    Michael Hartl, Jan 12, 2005
    #14
  15. list and generators (WAS: counting items)

    Michael Hartl wrote:
    > That's cool! Of course, walk returns a generator, so using a list
    > comprehension to turn it into a list seems natural, but I didn't
    > realize that list() does the same thing (and neither, apparently, did
    > the original implementor) -- although, with a little reflection, it
    > obviously must!


    Yup. Also worth noting is that if you want the scoping rules of
    generator expression, but need a list instead, you can just call list
    with the generator expression:

    py> x
    Traceback (most recent call last):
    File "<interactive input>", line 1, in ?
    NameError: name 'x' is not defined
    py> [pow(x, 7, 23) for x in range(10)]
    [0, 1, 13, 2, 8, 17, 3, 5, 12, 4]
    py> x
    9
    py> del x
    py> x
    Traceback (most recent call last):
    File "<interactive input>", line 1, in ?
    NameError: name 'x' is not defined
    py> list(pow(x, 7, 23) for x in xrange(10))
    [0, 1, 13, 2, 8, 17, 3, 5, 12, 4]
    py> x
    Traceback (most recent call last):
    File "<interactive input>", line 1, in ?
    NameError: name 'x' is not defined

    Note that with the generator expression, 'x' doesn't get leaked to the
    enclosing scope.

    Steve
     
    Steven Bethard, Jan 12, 2005
    #15
  16. On Wed, 12 Jan 2005 18:07:47 GMT, "Andrew Koenig" <> wrote:

    >"It's me" <> wrote in message
    >news:ukdFd.10645$...
    >
    >> 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)

    >
    >How about this?
    >
    > def totallen(x):
    > if isinstance(x, (list, tuple, dict)):
    > return sum(map(totallen, x))
    > return 1


    Since the requirement is to _count_, not flatten, ISTM your solution is best so far ;-)

    Regards,
    Bengt Richter
     
    Bengt Richter, Jan 13, 2005
    #16
  17. It's me

    Craig Ringer Guest

    On Wed, 2005-01-12 at 20:10 +0100, Bernhard Herzog wrote:
    > "It's me" <> 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))))]
    >
    > ;-)


    If it means I _never_ have to see that list comprehension again, then
    seeing 'flatten' go into itertools would make me very, very happy :p

    --
    Craig Ringer
     
    Craig Ringer, Jan 13, 2005
    #17
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Rob Meade

    Counting items in an array?

    Rob Meade, Nov 25, 2003, in forum: ASP .Net
    Replies:
    4
    Views:
    8,297
    Rob Meade
    Nov 25, 2003
  2. Andrew Banks

    Counting items and returning values

    Andrew Banks, Apr 1, 2004, in forum: ASP .Net
    Replies:
    3
    Views:
    347
    Cliff Harris
    Apr 1, 2004
  3. Replies:
    1
    Views:
    753
    Damien
    May 24, 2005
  4. Dan
    Replies:
    14
    Views:
    466
  5. edwardfredriks

    counting up instead of counting down

    edwardfredriks, Sep 6, 2005, in forum: Javascript
    Replies:
    6
    Views:
    223
    Dr John Stockton
    Sep 7, 2005
Loading...

Share This Page