counting items

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • It's me

    counting items

    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,(l ist,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,(l ist,tuple,dict) ):
    i += len(x)
    else:
    i += 1

    but that's so C-like...

    Thanks,


  • Andrew Koenig

    #2
    Re: counting items

    "It's me" <itsme@yahoo.co m> wrote in message
    news:ukdFd.1064 5$5R.2000@newss vr21.news.prodi gy.com...
    [color=blue]
    > 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)[/color]

    How about this?

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


    Comment

    • Paul McGuire

      #3
      Re: counting items

      "It's me" <itsme@yahoo.co m> wrote in message
      news:ukdFd.1064 5$5R.2000@newss vr21.news.prodi gy.com...[color=blue]
      > 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)
      >[/color]
      <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


      Comment

      • Mark McEahern

        #4
        Re: counting items

        It's me wrote:
        [color=blue]
        >Okay, I give up.
        >
        >What's the best way to count number of items in a list [that may contain lists]?
        >
        >[/color]
        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)

        Comment

        • It's me

          #5
          Re: counting items

          Thanks.

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


          "Paul McGuire" <ptmcg@austin.r r._bogus_.com> wrote in message
          news:aKdFd.8991 $RW3.7375@fe1.t exas.rr.com...[color=blue]
          > "It's me" <itsme@yahoo.co m> wrote in message
          > news:ukdFd.1064 5$5R.2000@newss vr21.news.prodi gy.com...[color=green]
          > > 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[/color][/color]
          don't[color=blue][color=green]
          > > want it to be 4)
          > >[/color]
          > <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.[/color]
          I[color=blue]
          > *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[/color]
          of[color=blue]
          > flatten() routine in the std dist, perhaps itertools?
          >
          > -- Paul
          >
          >[/color]


          Comment

          • It's me

            #6
            Re: counting items

            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(flatt en(data)):
            val_to_pos[x] = i + 1
            print val_to_pos



            "It's me" <itsme@yahoo.co m> wrote in message
            news:ukdFd.1064 5$5R.2000@newss vr21.news.prodi gy.com...[color=blue]
            > 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,(l ist,tuple,dict) )]
            > b=sum(lambda(x) for x in a)
            >
            > and that didn't work because I get a TypeError from the len function[/color]
            (don't[color=blue]
            > know why)
            >
            > I can, of course:
            >
            > i=0
            > for x in a:
            > if isinstance(x,(l ist,tuple,dict) ):
            > i += len(x)
            > else:
            > i += 1
            >
            > but that's so C-like...
            >
            > Thanks,
            >
            >[/color]


            Comment

            • Anthony

              #7
              Re: counting items

              On Wed, 12 Jan 2005 17:42:50 GMT, It's me <itsme@yahoo.co m> wrote:[color=blue]
              > Okay, I give up.
              >
              > What's the best way to count number of items in a list?[/color]

              How long is a piece of string? There are many different ways, which
              give you different trade offs.
              [color=blue]
              > 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.[/color]

              And is very unreadable.
              [color=blue]
              > I tried:
              >
              > g=lambda x: (1,len(x))[isinstance(x,(l ist,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)[/color]

              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,fl oat]]
              print listLengths

              compoundLength = len(compoundLis t) - 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.BrIGgS@ gmAiL.CoM
              -----------------------------------------------------

              Comment

              • It's me

                #8
                Re: counting items

                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(flatt en(data))])

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


                Thanks everybody.



                "Mark McEahern" <marklists@mcea hern.com> wrote in message
                news:mailman.57 9.1105554265.22 381.python-list@python.org ...[color=blue]
                > It's me wrote:
                >[color=green]
                > >Okay, I give up.
                > >
                > >What's the best way to count number of items in a list [that may contain[/color][/color]
                lists]?[color=blue][color=green]
                > >
                > >[/color]
                > 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)
                >[/color]


                Comment

                • Steven Bethard

                  #9
                  Re: counting items

                  Mark McEahern wrote:[color=blue]
                  > It's me wrote:
                  >[color=green]
                  >> Okay, I give up.
                  >>
                  >> What's the best way to count number of items in a list [that may
                  >> contain lists]?
                  >>
                  >>[/color]
                  > 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)
                  >[/color]

                  Beware:

                  py> list(iterall(['a']))
                  Traceback (most recent call last):
                  File "<interacti ve input>", line 1, in ?
                  File "<interacti ve input>", line 4, in iterall
                  ...
                  File "<interacti ve 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

                  Comment

                  • Bernhard Herzog

                    #10
                    Re: counting items

                    "It's me" <itsme@yahoo.co m> writes:
                    [color=blue]
                    > May be flatten should be build into the language somehow....[/color]

                    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/

                    Comment

                    • Michael Hartl

                      #11
                      Re: counting items

                      There's a great function called "walk" at that iterates over arbitrary
                      data (and is recursion-proof) at



                      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

                      Comment

                      • Leif K-Brooks

                        #12
                        Re: counting items

                        Paul McGuire wrote:[color=blue]
                        > Considering how often this comes up, might there be a place for some sort of
                        > flatten() routine in the std dist, perhaps itertools?[/color]

                        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.

                        Comment

                        • Steven Bethard

                          #13
                          Re: counting items

                          Michael Hartl wrote:[color=blue]
                          > (Once you can iterate over an arbitrary sequence, the
                          > flattened version is just
                          > [element for element in walk(sequence)].)[/color]

                          Or, better yet:

                          list(walk(seque nce))

                          Steve

                          Comment

                          • Michael Hartl

                            #14
                            Re: counting items

                            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

                            Comment

                            • Steven Bethard

                              #15
                              list and generators (WAS: counting items)

                              Michael Hartl wrote:[color=blue]
                              > 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![/color]

                              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 "<interacti ve 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 "<interacti ve 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 "<interacti ve 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

                              Comment

                              Working...