complex data structure - insert value

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

    #1

    complex data structure - insert value

    I'm converting a Perl script to Python and have run into something I'm
    not sure how to do in Python.

    In Perl, I am running through a couple loops and inserting values
    directly into a complex data structure (array->hash->array). This
    isn't the actual code, but should demonstrate the general idea:

    foreach $bar_count(@bar s) {
    foreach $el_count(@els) {
    $var = somefunc($bar_c ount,$el_count) ;
    $data[$bar_count]->{'CC'}->[$el_count] = $var;
    }
    }

    Basically I'd like to do the same thing in Python. I've written a
    convoluted test script where I can print an element:

    print data[0]['CC'][1]

    but I can't insert directly like I do in Perl (data[0]['CC'][1] =
    $var). In my test script I've simply initialized my lists and
    dictionary at the beginning of the script, not by iterating an
    inserting values as in the Perl example.

    Any advice appreciated...t hanks.
  • Jeffrey Froman

    #2
    Re: complex data structure - insert value

    spar wrote:
    [color=blue]
    > Basically I'd like to do the same thing in Python. I've written a
    > convoluted test script where I can print an element:
    >
    > print data[0]['CC'][1]
    >
    > but I can't insert directly like I do in Perl (data[0]['CC'][1] =
    > $var).[/color]

    This should work fine, though in python this would result in assignment, not
    insertion:

    *************** ************[color=blue][color=green][color=darkred]
    >>> #Assignment:
    >>> x=[{'foo':[1,2,3]}]
    >>> x[0]['foo'][1] = 'bar'
    >>> x[/color][/color][/color]
    [{'foo': [1, 'bar', 3]}]
    [color=blue][color=green][color=darkred]
    >>> #Insertion:
    >>> x[0]['foo'].insert(2, 'baz')
    >>> x[/color][/color][/color]
    [{'foo': [1, 'bar', 'baz', 3]}]

    *************** ************

    Jeffrey

    Comment

    • Nick Craig-Wood

      #3
      Re: complex data structure - insert value

      Jeffrey Froman <jeffrey@fro.ma n> wrote:[color=blue]
      > spar wrote:
      >[color=green]
      > > Basically I'd like to do the same thing in Python. I've written a
      > > convoluted test script where I can print an element:
      > >
      > > print data[0]['CC'][1]
      > >
      > > but I can't insert directly like I do in Perl (data[0]['CC'][1] =
      > > $var).[/color]
      >
      > This should work fine, though in python this would result in assignment, not
      > insertion:
      >[color=green][color=darkred]
      > >>> #Assignment:
      > >>> x=[{'foo':[1,2,3]}]
      > >>> x[0]['foo'][1] = 'bar'
      > >>> x[/color][/color]
      > [{'foo': [1, 'bar', 3]}]
      >[color=green][color=darkred]
      > >>> #Insertion:
      > >>> x[0]['foo'].insert(2, 'baz')
      > >>> x[/color][/color]
      > [{'foo': [1, 'bar', 'baz', 3]}][/color]

      The OP is relying on a perl feature called auto-vivification. In perl
      speak when you do

      $data->[0]->{'CC'}->[1] = "spam";

      The only thing that has to exist is the array reference in $data.
      Perl will then auto-vivify the hash then the second arrayref.

      Python doesn't do this in its standard list and dict objects. So
      either you create some subclasses which do (which isn't that hard -
      need to overload __setitem__ in both cases and do the perl thing).

      Alternatively you can do it the python way... The original

      foreach $bar_count(@bar s) {
      foreach $el_count(@els) {
      $var = somefunc($bar_c ount,$el_count) ;
      $data[$bar_count]->{'CC'}->[$el_count] = $var;
      }
      }

      becomes

      def somefunc(a,b): return 1
      bars=[1, 2, 3, 4, 5]
      els=[7, 8]

      data = []
      for bar_count in bars:
      for el_count in els:
      var = somefunc(bar_co unt, el_count)
      while bar_count >= len(data):
      data.append({})
      l = data[bar_count].setdefault('CC ', [])
      while el_count >= len(l):
      l.append(None)
      l[el_count] = var

      [color=blue][color=green][color=darkred]
      >>> pprint(data)[/color][/color][/color]
      [{},
      {'CC': [None, None, None, None, None, None, None, 1, 1]},
      {'CC': [None, None, None, None, None, None, None, 1, 1]},
      {'CC': [None, None, None, None, None, None, None, 1, 1]},
      {'CC': [None, None, None, None, None, None, None, 1, 1]},
      {'CC': [None, None, None, None, None, None, None, 1, 1]}]


      Or you may prefer this which you can't do in perl (because keys of
      hashes can only be strings)

      data = {}
      for bar_count in bars:
      for el_count in els:
      var = somefunc(bar_co unt, el_count)
      data[(bar_count,'CC' ,el_count)] = var
      [color=blue][color=green][color=darkred]
      >>> pprint(data)[/color][/color][/color]
      {(1, 'CC', 7): 1,
      (1, 'CC', 8): 1,
      (2, 'CC', 7): 1,
      (2, 'CC', 8): 1,
      (3, 'CC', 7): 1,
      (3, 'CC', 8): 1,
      (4, 'CC', 7): 1,
      (4, 'CC', 8): 1,
      (5, 'CC', 7): 1,
      (5, 'CC', 8): 1}

      It does't produce quite the same data structures but it may be useful
      for you.

      However one thing I've noticed from converting quite a few perl
      programs to python is that constant 'CC' in a hash is indicative of
      the fact that you really should be defining a class, of which CC
      becomes an attribute or method. In perl the way is to define complex
      data structures of hashes and lists, but in python because its so much
      easier to create a class when you want it, do that.

      So whenever you see $hash->{constant_stri ng} you should be thinking -
      hmm shouldn't that be a class. And when you've made it a class you'll
      find that you have functions which should be methods of that class,
      and before you know it you'll find your program looks a lot tidier!

      --
      Nick Craig-Wood <nick@craig-wood.com> -- http://www.craig-wood.com/nick

      Comment

      • spar

        #4
        Re: complex data structure - insert value

        Nick Craig-Wood <nick@craig-wood.com> wrote in message news:<slrncmhu6 1.aqa.nick@iris hsea.home.craig-wood.com>...
        [color=blue]
        > def somefunc(a,b): return 1
        > bars=[1, 2, 3, 4, 5]
        > els=[7, 8]
        >
        > data = []
        > for bar_count in bars:
        > for el_count in els:
        > var = somefunc(bar_co unt, el_count)
        > while bar_count >= len(data):
        > data.append({})
        > l = data[bar_count].setdefault('CC ', [])
        > while el_count >= len(l):
        > l.append(None)
        > l[el_count] = var
        >
        >[color=green][color=darkred]
        > >>> pprint(data)[/color][/color]
        > [{},
        > {'CC': [None, None, None, None, None, None, None, 1, 1]},
        > {'CC': [None, None, None, None, None, None, None, 1, 1]},
        > {'CC': [None, None, None, None, None, None, None, 1, 1]},
        > {'CC': [None, None, None, None, None, None, None, 1, 1]},
        > {'CC': [None, None, None, None, None, None, None, 1, 1]}][/color]


        Thanks, this is close...I'll have to play with it a bit. I've done
        Perl for quite sometime, but am new to Python.

        My example code didn't exactly show what I'm trying to do. The data
        structure should actually look something like this (think of each
        array element as a musical bar, each dict element ('HH', etc.) is an
        instrument in that bar, and the list within the dict represent beats
        for that instrument within the bar):

        [{},
        {'CC': ['-', '-', '-', '-'], 'HH': ['x', 'x', 'x', 'x'], 'SD': ['-',
        '-', 'o', '-']},
        {'CC': ['x', '-', '-', '-'], 'HH': ['x', 'x', 'x', 'x'], 'SD': ['o',
        '-', 'o', '-']},
        {'CC': ['-', '-', '-', '-'], 'HH': ['x', 'x', 'x', 'x'], 'SD': ['-',
        '-', 'o', '-']},
        {'CC': ['x', '-', '-', '-'], 'HH': ['x', 'x', 'x', 'x'], 'SD': ['o',
        '-', 'o', '-']}]

        So this shows bars 1-4 (there is no bar 0, so it's empty), each bar
        has three instruments ('CC', 'HH', and 'SD') and each instrument shows
        what is to be played on beats (subdivisions) 1-4 (actually there will
        be 16 subdivisions representing 16 16th notes).

        I think I can take your code and mold it into what I need. Thanks...

        Comment

        • Alex Martelli

          #5
          Re: complex data structure - insert value

          spar <spariam@hotmai l.com> wrote:
          ...[color=blue]
          > foreach $bar_count(@bar s) {
          > foreach $el_count(@els) {
          > $var = somefunc($bar_c ount,$el_count) ;
          > $data[$bar_count]->{'CC'}->[$el_count] = $var;
          > }
          > }[/color]

          Not quite sure what you mean, but maybe s/thing like...:

          data = {}

          for bar_count in bars:
          for el_count in els:
          var = somefunc(bar_co unt, el_count)
          subdict = data.set_defaul t(bar_count, {})
          subdict = subdict.set_def ault('CC', {})
          subdict[el_count] = var

          ....?


          Alex

          Comment

          Working...