unpaking sequences of unknown length

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Anthra Norell

    #1

    unpaking sequences of unknown length

    Hi,

    I keep working around a little problem with unpacking in cases in which I don't know how many elements I get. Consider this:

    def tabulate_lists (*arbitray_numb er_of_lists):
    table = zip (arbitray_numbe r_of_lists)
    for record in table:
    # etc ...

    This does not work, because the zip function also has an *arg parameter, which expects an arbitrary length enumeration of arguments
    which it would turn into a tuple (lists in this case). Now my function does exactly the same thing ahead of zip. So, before I pass
    the tuple "arbitrary_numb er_of_lists" to zip, I 'd need to unpack it but the only way I know of is into variables:

    list1, list2, list3 = arbitrary_numbe r_of_lists
    zip (list1, list2, list3)

    With arbitrary number of lists it cannot be done this way.

    Question: Is there an unpacking mechanism for cases in which I don't know--and don't need to know--how many elements I get, or an
    argument passing mechanism that is the inverse of the tuplifier (*args)?

    table = zip (&arbitrary_num ber_of_lists) # I invent '&' to illustrate

    I preclude passing a pre-zipped table as a solution, because all function-related argument processing should be done by the
    function, not by the caller. Supposing my tabulator should auto-format a printout. It would need to analyze each column (e.g.
    maxima, minima, max length of strings, etc.) That would be a lot simpler with column lists than with record lists, unless I undo
    what the caller had to do, because the function couldn't ... a lot of in and out ...

    Of course I could code a code edit and exec () it.

    names_of_lists = ','.join (['list%d' % n for n in range (len (arbitrary_numb er_of_lists)])
    exec ('"%s = arbitrary_numbe r_of_lists"'% names_of_lists)
    exec ('"table = zip (%s)"' % names_of_lists)

    That should work, but it looks loathsome to me.


    Has anyone come across a similar problem and found an elegant solution he might want to share?

    Frederic


  • Diez B. Roggisch

    #2
    Re: unpaking sequences of unknown length

    I keep working around a little problem with unpacking in cases in which I don't know how many elements I get. Consider this:
    >
    def tabulate_lists (*arbitray_numb er_of_lists):
    table = zip (arbitray_numbe r_of_lists)
    for record in table:
    # etc ...
    >
    This does not work, because the zip function also has an *arg parameter, which expects an arbitrary length enumeration of arguments
    which it would turn into a tuple (lists in this case). Now my function does exactly the same thing ahead of zip. So, before I pass
    the tuple "arbitrary_numb er_of_lists" to zip, I 'd need to unpack it but the only way I know of is into variables:
    >
    list1, list2, list3 = arbitrary_numbe r_of_lists
    zip (list1, list2, list3)

    I don't get your problem here. This works for me:

    args = [range(5) for i in xrange(5)]

    print zip(*args)
    With arbitrary number of lists it cannot be done this way.
    >
    Question: Is there an unpacking mechanism for cases in which I don't know--and don't need to know--how many elements I get, or an
    argument passing mechanism that is the inverse of the tuplifier (*args)?
    No.

    It looks a little bit as if you aren't aware of the symetry behind the *
    and **-argument-passing schemes. I suggest reading up on them.

    Diez

    Comment

    • Diez B. Roggisch

      #3
      Re: unpaking sequences of unknown length

      >Question: Is there an unpacking mechanism for cases in which I don't
      >know--and don't need to know--how many elements I get, or an
      >argument passing mechanism that is the inverse of the tuplifier (*args)?
      >
      No.
      >
      It looks a little bit as if you aren't aware of the symetry behind the *
      and **-argument-passing schemes. I suggest reading up on them.
      Sorry - I was somewhat unconcentrated and missed the last part of the
      sentence. So it is

      No "generalize d", yes, the inverse of *args is foo(*args)

      Sorry for the confusion.

      Diez

      Comment

      • Gerard Flanagan

        #4
        Re: unpaking sequences of unknown length


        Anthra Norell wrote:
        Hi,
        >
        I keep working around a little problem with unpacking in cases in which I don't know how many elements I get. Consider this:
        >
        def tabulate_lists (*arbitray_numb er_of_lists):
        table = zip (arbitray_numbe r_of_lists)
        for record in table:
        # etc ...
        >
        This does not work, because the zip function also has an *arg parameter, which expects an arbitrary length enumeration of arguments
        maybe I don't understand the problem properly, but you can use '*args'
        as 'args' or as '*args', if you see what I mean!, ie.

        def tabulate_lists (*arbitray_numb er_of_lists):
        table = zip (*arbitray_numb er_of_lists)
        for record in table:
        # etc ...

        for example:

        def sum_columns(*ro ws):
        for col in zip(*rows):
        yield sum(col)

        for i, s in enumerate( sum_columns( [1,2], [3,2], [5,1] ) ):
        print 'Column %s: SUM=%s' % (i,s)

        Column 0: SUM=9
        Column 1: SUM=5

        -----------------------------------------------------

        alternatively:

        import itertools as it

        def sum_columns2( iterable ):
        for col in it.izip( *iterable ):
        yield sum(col)

        def iter_rows():
        yield [1,2]
        yield [3,2]
        yield [5,1]

        print list( sum_columns2( iter_rows() ) )

        #(izip isn't necessary here, zip would do.)

        -----------------------------------

        Gerard

        Comment

        • Anthra Norell

          #5
          Re: unpaking sequences of unknown length

          I get it!
          >>def f (*a):
          print a
          print zip (a) # My mistake
          print zip (*a) # Gerard's solution.
          >>f (l1, l2, l3)
          ([1, 2, 3], [4, 5, 6], [7, 5, 34]) # Argument: tuple of lists
          [([1, 2, 3],), ([4, 5, 6],), ([7, 5, 34],)] # My mistake
          [(1, 4, 7), (2, 5, 5), (3, 6, 34)] # That's what I want

          Thank you all

          Frederic


          ----- Original Message -----
          From: "Gerard Flanagan" <grflanagan@yah oo.co.uk>
          Newsgroups: comp.lang.pytho n
          To: <python-list@python.org >
          Sent: Sunday, August 27, 2006 2:59 PM
          Subject: Re: unpaking sequences of unknown length

          >
          Anthra Norell wrote:
          Hi,

          I keep working around a little problem with unpacking in cases in which I don't know how many elements I get. Consider this:

          def tabulate_lists (*arbitray_numb er_of_lists):
          table = zip (arbitray_numbe r_of_lists)
          for record in table:
          # etc ...

          This does not work, because the zip function also has an *arg parameter, which expects an arbitrary length enumeration of
          arguments
          >
          maybe I don't understand the problem properly, but you can use '*args'
          as 'args' or as '*args', if you see what I mean!, ie.
          >
          def tabulate_lists (*arbitray_numb er_of_lists):
          table = zip (*arbitray_numb er_of_lists)
          for record in table:
          # etc ...
          >
          for example:
          >
          def sum_columns(*ro ws):
          for col in zip(*rows):
          yield sum(col)
          >
          for i, s in enumerate( sum_columns( [1,2], [3,2], [5,1] ) ):
          print 'Column %s: SUM=%s' % (i,s)
          >
          Column 0: SUM=9
          Column 1: SUM=5
          >
          -----------------------------------------------------
          >
          alternatively:
          >
          import itertools as it
          >
          def sum_columns2( iterable ):
          for col in it.izip( *iterable ):
          yield sum(col)
          >
          def iter_rows():
          yield [1,2]
          yield [3,2]
          yield [5,1]
          >
          print list( sum_columns2( iter_rows() ) )
          >
          #(izip isn't necessary here, zip would do.)
          >
          -----------------------------------
          >
          Gerard
          >
          --
          http://mail.python.org/mailman/listinfo/python-list

          Comment

          Working...