interleaving dictionary values

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • j1o1h1n@gmail.com

    #1

    interleaving dictionary values


    Hello,

    I was trying to create a flattened list of dictionary values where each
    value is a list, and I was hoping to do this in some neat functionally
    style, in some brief, throwaway line so that it would assume the
    insignificance that it deserves in the grand scheme of my program.

    I had in mind something like this:
    >>interleave([1, 2, 3], [4,5], [7, 8, 9])
    [1, 4, 7, 2, 5, 8, 3, 9]

    I played for a while with zip(), [some newfangled python keyword, that
    I was truly shocked to find has been hiding at the bottom of the list
    built in functions since version 2.0], before giving up and going back
    to trusty old map(), long celebrated for making code hard to read:
    >>map(None, [1, 2, 3], [4,5], [7, 8, 9])
    [(1, 4, 7), (2, 5, 8), (3, None, 9)]

    This is basically it. It then becomes:
    >>filter(None , flatten(map(Non e, [1, 2, 3], [4,5], [7, 8, 9])))
    [1, 4, 7, 2, 5, 8, 3, 9]

    filter(None, - my brain parses that automatically now. This is not so
    bad. Flatten is snitched from ASPN/Cookbook/Python/Recipe/363051,
    thank you Jordan Callicoat, Mike C. Fletcher:

    def flatten(l, ltypes=(list, tuple)):
    i = 0
    while (i < len(l)):
    while (isinstance(l[i], ltypes)):
    l[i:i+1] = list(l[i])
    i += 1
    return l

    Trouble is then getting map() to play with the result of dict.values().
    I only worked this out while writing this post, of course.

    Given a dictionary like d = { "a" : [1, 2, 3], "b" : [4, 5], "c" : [7,
    8, 9]} - I was hoping to do this:

    map(None, d.values())

    But instead I (finally worked out I could) do this:

    apply(map, tuple([None] + d.values()))

    So... my bit of code becomes:

    filter(None, flatten(map(Non e, apply(map, tuple([None] +
    d.values())))))

    It fits on one line, but it feels far more evil than I set out to be.
    The brackets at the end are bad for my epilepsy.

    Surely there is there some nice builtin function I have missed?

    --
    | John J. Lehmann, j1o1h1n(@)gmail .com
    + [lost-in-translation] "People using public transport look stern, and
    handbag
    + snatchers increase the ill feeling." A Japanese woman, Junko, told
    the paper:
    + "For us, Paris is the dream city. The French are all beautiful and
    elegant
    + And then, when we arrive..."

  • Roberto Bonvallet

    #2
    Re: interleaving dictionary values

    j1o1h1n@gmail.c om wrote:
    [...]
    I had in mind something like this:
    >
    >>>interleave ([1, 2, 3], [4,5], [7, 8, 9])
    [1, 4, 7, 2, 5, 8, 3, 9]
    [...]
    But instead I (finally worked out I could) do this:
    >
    apply(map, tuple([None] + d.values()))
    apply is deprecated, it should be map(None, *d.values())
    So... my bit of code becomes:
    >
    filter(None, flatten(map(Non e, apply(map, tuple([None] +
    d.values())))))
    >
    It fits on one line, but it feels far more evil than I set out to be.
    The brackets at the end are bad for my epilepsy.
    >
    Surely there is there some nice builtin function I have missed?
    You have missed the "it doesn't need to be a one-liner" motto :)
    >>def interleave(*arg s):
    .... result = []
    .... for items in map(None, *args):
    .... result.extend([x for x in items if x is not None])
    .... return result
    ....
    >>interleave([1, 2, 3], [4,5], [7, 8, 9])
    [1, 4, 7, 2, 5, 8, 3, 9]

    Cheers,
    --
    Roberto Bonvallet

    Comment

    • Neil Cerutti

      #3
      Re: interleaving dictionary values

      On 2006-11-21, j1o1h1n@gmail.c om <j1o1h1n@gmail. comwrote:
      I had in mind something like this:
      >
      >>>interleave ([1, 2, 3], [4,5], [7, 8, 9])
      [1, 4, 7, 2, 5, 8, 3, 9]
      >
      [...] before giving up and going back to trusty old map(), long
      celebrated for making code hard to read:
      >
      >>>map(None, [1, 2, 3], [4,5], [7, 8, 9])
      [(1, 4, 7), (2, 5, 8), (3, None, 9)]
      >
      This is basically it. It then becomes:
      >
      >>>filter(Non e, flatten(map(Non e, [1, 2, 3], [4,5], [7, 8, 9])))
      [1, 4, 7, 2, 5, 8, 3, 9]
      You can use itertools.chain instead of flatten:
      >>from itertools import chain
      >>filter(None , chain(*map(None , [1, 2, 3], [4, 5], [7, 8, 9])))
      [1, 4, 7, 2, 5, 8, 3, 9]
      Trouble is then getting map() to play with the result of dict.values().
      I only worked this out while writing this post, of course.
      >
      Given a dictionary like d = { "a" : [1, 2, 3], "b" : [4, 5], "c" : [7,
      8, 9]} - I was hoping to do this:
      >
      map(None, d.values())
      You need the * to "unpack" the list. It has generally taken the
      place of apply.
      >>map(None, *d.values())
      [(1, 7, 4), (2, 8, 5), (3, 9, None)]
      So... my bit of code becomes:
      >>filter(None , chain(*map(None , *d.values())))
      [1, 7, 4, 2, 8, 5, 3, 9]

      I don't think that the specific ordering that's achieved has any
      valuable significance. You might be just as happy with the
      simpler:
      >>list(chain(*d .values()))
      [1, 2, 3, 7, 8, 9, 4, 5]

      --
      Neil Cerutti
      Weight Watchers will meet at 7 p.m. Please use large double door at the side
      entrance. --Church Bulletin Blooper

      Comment

      • bearophileHUGS@lycos.com

        #4
        Re: interleaving dictionary values

        d = {"a": [1, 2, 3], "b": [4, 5], "c": [7, 8, 9]}

        # Simple solution:
        result = []
        for l in d.itervalues():
        result.extend(l )
        print result

        # Alternative:
        from itertools import chain
        print list( chain(*d.iterva lues()) )

        I don't know what's the faster solution, the first one seem more
        readable and it's probably fast enough.

        Bye,
        bearophile

        Comment

        • Noah Rawlins

          #5
          Re: interleaving dictionary values

          j1o1h1n@gmail.c om wrote:
          filter(None, - my brain parses that automatically now. This is not so
          bad. Flatten is snitched from ASPN/Cookbook/Python/Recipe/363051,
          thank you Jordan Callicoat, Mike C. Fletcher:
          >
          def flatten(l, ltypes=(list, tuple)):
          i = 0
          while (i < len(l)):
          while (isinstance(l[i], ltypes)):
          l[i:i+1] = list(l[i])
          i += 1
          return l
          >
          On a side note, that version of flatten doesn't handle an empty list as
          the last element of a list...
          >>flatten([1, 2, 3, []])
          Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
          File "<stdin>", line 4, in flatten
          IndexError: list index out of range

          You need a try: in there or something...

          def flatten(l, ltypes=(list, tuple)):
          i = 0
          while(i < len(l)):
          try:
          while(isinstanc e(l[i], ltypes)):
          l[i:i+1] = list(l[i])
          i += 1
          except IndexError:
          pass
          return l

          noah

          Comment

          • Tuomas

            #6
            Re: interleaving dictionary values

            j1o1h1n@gmail.c om wrote:
            Hello,
            >
            I was trying to create a flattened list of dictionary values where each
            value is a list, and I was hoping to do this in some neat functionally
            style, in some brief, throwaway line so that it would assume the
            insignificance that it deserves in the grand scheme of my program.
            >
            I had in mind something like this:
            >
            >
            >>>>interleav e([1, 2, 3], [4,5], [7, 8, 9])
            >
            [1, 4, 7, 2, 5, 8, 3, 9]
            >
            I played for a while with zip(), [some newfangled python keyword, that
            I was truly shocked to find has been hiding at the bottom of the list
            built in functions since version 2.0], before giving up and going back
            to trusty old map(), long celebrated for making code hard to read:
            >
            >
            >>>>map(None, [1, 2, 3], [4,5], [7, 8, 9])
            >
            [(1, 4, 7), (2, 5, 8), (3, None, 9)]
            >
            This is basically it. It then becomes:
            >
            >
            >>>>filter(None , flatten(map(Non e, [1, 2, 3], [4,5], [7, 8, 9])))
            >
            [1, 4, 7, 2, 5, 8, 3, 9]
            >
            filter(None, - my brain parses that automatically now. This is not so
            bad. Flatten is snitched from ASPN/Cookbook/Python/Recipe/363051,
            thank you Jordan Callicoat, Mike C. Fletcher:
            >
            def flatten(l, ltypes=(list, tuple)):
            i = 0
            while (i < len(l)):
            while (isinstance(l[i], ltypes)):
            l[i:i+1] = list(l[i])
            i += 1
            return l
            >
            Trouble is then getting map() to play with the result of dict.values().
            I only worked this out while writing this post, of course.
            >
            Given a dictionary like d = { "a" : [1, 2, 3], "b" : [4, 5], "c" : [7,
            8, 9]} - I was hoping to do this:
            >
            map(None, d.values())
            >
            But instead I (finally worked out I could) do this:
            >
            apply(map, tuple([None] + d.values()))
            >
            So... my bit of code becomes:
            >
            filter(None, flatten(map(Non e, apply(map, tuple([None] +
            d.values())))))
            >
            It fits on one line, but it feels far more evil than I set out to be.
            The brackets at the end are bad for my epilepsy.
            >
            Surely there is there some nice builtin function I have missed?
            >
            --
            | John J. Lehmann, j1o1h1n(@)gmail .com
            + [lost-in-translation] "People using public transport look stern, and
            handbag
            + snatchers increase the ill feeling." A Japanese woman, Junko, told
            the paper:
            + "For us, Paris is the dream city. The French are all beautiful and
            elegant
            + And then, when we arrive..."
            >
            What about:
            >>d = { "a" : [1, 2, 3], "b" : [4, 5], "c" : [7, 8, 9]}
            >>L=[]
            >>for x in d.values(): L.extend(x)
            ....
            >>L
            [1, 2, 3, 7, 8, 9, 4, 5]

            or a little curious:
            >>L=[]
            >>map(L.exten d, d.values())
            [None, None, None]
            >>L
            [1, 2, 3, 7, 8, 9, 4, 5]

            TV

            Comment

            Working...