list comprehension

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

    list comprehension

    Hello,

    Trying to change a string(x,y values) such as :

    s = "114320,698 08 114272,69920 113568,71600 113328,72272"

    into (x,-y):

    out = "114320,-69808 114272,-69920 113568,-71600 113328,-72272"

    I tried this:

    print [(a[0],-a[1] for a in x.split(',')) for x in e]

    But it doesn't work. Can anyone suggest why or suggest an alternative
    way? The text strings are significantly bigger than this so performance
    is important.

    TIA,

    Guy
  • Aahz

    #2
    Re: list comprehension

    In article <c7mii9$988$1@l ust.ihug.co.nz> ,
    Guy Robinson <guy@NOSPAM.r-e-d.co.nz> wrote:[color=blue]
    >
    >Trying to change a string(x,y values) such as :
    >
    >s = "114320,698 08 114272,69920 113568,71600 113328,72272"
    >
    >into (x,-y):
    >
    >out = "114320,-69808 114272,-69920 113568,-71600 113328,-72272"
    >
    >I tried this:
    >
    >print [(a[0],-a[1] for a in x.split(',')) for x in e]
    >
    >But it doesn't work. Can anyone suggest why or suggest an alternative
    >way? The text strings are significantly bigger than this so performance
    >is important.[/color]

    When in doubt, break a problem into smaller steps. Let me play Socrates
    for a minute: what's the first step in working with your dataset?
    --
    Aahz (aahz@pythoncra ft.com) <*> http://www.pythoncraft.com/

    Adopt A Process -- stop killing all your children!

    Comment

    • Guy Robinson

      #3
      Re: list comprehension

      This works I was just wondering if something could be written more
      concisely and hopefully faster:

      s = "114320,698 08 114272,69920 113568,71600 113328,72272"
      e = s.split(' ')
      out =''
      for d in e:
      d =d.split(',')
      out +='%s,%d ' %(d[0],-int(d[1]))
      print out

      Guy

      Aahz wrote:
      [color=blue]
      > In article <c7mii9$988$1@l ust.ihug.co.nz> ,
      > Guy Robinson <guy@NOSPAM.r-e-d.co.nz> wrote:
      >[color=green]
      >>Trying to change a string(x,y values) such as :
      >>
      >>s = "114320,698 08 114272,69920 113568,71600 113328,72272"
      >>
      >>into (x,-y):
      >>
      >>out = "114320,-69808 114272,-69920 113568,-71600 113328,-72272"
      >>
      >>I tried this:
      >>
      >>print [(a[0],-a[1] for a in x.split(',')) for x in e]
      >>
      >>But it doesn't work. Can anyone suggest why or suggest an alternative
      >>way? The text strings are significantly bigger than this so performance
      >>is important.[/color]
      >
      >
      > When in doubt, break a problem into smaller steps. Let me play Socrates
      > for a minute: what's the first step in working with your dataset?[/color]

      Comment

      • Andrew Bennetts

        #4
        Re: list comprehension

        On Mon, May 10, 2004 at 12:32:20PM +1200, Guy Robinson wrote:[color=blue]
        > Hello,
        >
        > Trying to change a string(x,y values) such as :
        >
        > s = "114320,698 08 114272,69920 113568,71600 113328,72272"
        >
        > into (x,-y):
        >
        > out = "114320,-69808 114272,-69920 113568,-71600 113328,-72272"
        >
        > I tried this:
        >
        > print [(a[0],-a[1] for a in x.split(',')) for x in e]
        >
        > But it doesn't work. Can anyone suggest why or suggest an alternative
        > way? The text strings are significantly bigger than this so performance
        > is important.[/color]

        It has several syntax errors; (a[0],-a[1] for a in x.split(',')) is not a
        valid expression because list comprehensions are bracketed by square
        brackets, not parentheses. Also, the first part of a list comprehension,
        the expression to calculate each element, needs to be in parens to if it has
        a comma, so that the parser can disambiguate it from an ordinary list.

        I also don't know where you got 'e' from. Is it 's', or 's.split()'?

        If list comprenhensions grow unwieldy, just use a for loop. They're
        probably easier to read than a list comprehension that takes you ten minutes
        to concoct, and performance is almost identical. For the sake of answering
        your question, though, here's a expression that does what you ask:
        [color=blue][color=green][color=darkred]
        >>> s = "114320,698 08 114272,69920 113568,71600 113328,72272"
        >>> s.replace(',',' ,-')[/color][/color][/color]
        '114320,-69808 114272,-69920 113568,-71600 113328,-72272'

        You could do this with list comprehensions, e.g.:
        [color=blue][color=green][color=darkred]
        >>> ' '.join(['%s,-%s' % tuple(x) for x in [pairs.split(',' ) for pairs in s.split(' ')]])[/color][/color][/color]
        '114320,-69808 114272,-69920 113568,-71600 113328,-72272'

        But I don't really see the point, given the way you've described the
        problem.

        -Andrew.


        Comment

        • Shalabh Chaturvedi

          #5
          Re: list comprehension

          Guy Robinson wrote:
          [color=blue]
          > This works I was just wondering if something could be written more
          > concisely and hopefully faster:
          > s = "114320,698 08 114272,69920 113568,71600 113328,72272"
          > e = s.split(' ')
          > out =''[/color]

          outl = []
          [color=blue]
          > for d in e:
          > d =d.split(',')
          > out +='%s,%d ' %(d[0],-int(d[1]))[/color]

          outl.append(s) # where s is the string you construct
          out = ' '.join(outl)
          [color=blue]
          > print out
          >
          > Guy
          >[/color]

          It's faster to collect strings in a list and join them later than to
          concatenate strings one by one.

          Also, do you have to convert d[1] to int? If you are sure that it is
          always a positive integer, you can do '%s,-%s' % (d[0],d[1]).

          In fact you could even try to replace ',' with ',-' instead of splitting
          the string at all. Of course it depends on what the format of your
          incoming string is.

          --
          Shalabh


          Comment

          • Aahz

            #6
            Re: list comprehension

            In article <c7ml6k$c88$1@l ust.ihug.co.nz> ,
            Guy Robinson <guy@NOSPAM.r-e-d.co.nz> wrote:[color=blue]
            >
            >This works I was just wondering if something could be written more
            >concisely and hopefully faster:
            >
            >s = "114320,698 08 114272,69920 113568,71600 113328,72272"
            >e = s.split(' ')
            >out =''
            >for d in e:
            > d =d.split(',')
            > out +='%s,%d ' %(d[0],-int(d[1]))
            >print out[/color]

            Performance I can understand (which Shalabh addressed quite nicely), but
            why do you care about compressing the source code? This is simple,
            straightforward , and easy to read; surely that's more important than
            saving a few bytes?
            --
            Aahz (aahz@pythoncra ft.com) <*> http://www.pythoncraft.com/

            Adopt A Process -- stop killing all your children!

            Comment

            • Tim Roberts

              #7
              Re: list comprehension

              Guy Robinson <guy@NOSPAM.r-e-d.co.nz> wrote:
              [color=blue]
              >This works I was just wondering if something could be written more
              >concisely and hopefully faster:
              >
              >s = "114320,698 08 114272,69920 113568,71600 113328,72272"
              >e = s.split(' ')
              >out =''
              >for d in e:
              > d =d.split(',')
              > out +='%s,%d ' %(d[0],-int(d[1]))
              >print out[/color]

              Well, why not the more obvious: s.replace(',',' ,-')
              --
              - Tim Roberts, timr@probo.com
              Providenza & Boekelheide, Inc.

              Comment

              • Peter Otten

                #8
                Re: list comprehension

                Tim Roberts wrote:
                [color=blue]
                > Guy Robinson <guy@NOSPAM.r-e-d.co.nz> wrote:
                >[color=green]
                >>This works I was just wondering if something could be written more
                >>concisely and hopefully faster:
                >>
                >>s = "114320,698 08 114272,69920 113568,71600 113328,72272"
                >>e = s.split(' ')
                >>out =''
                >>for d in e:
                >> d =d.split(',')
                >> out +='%s,%d ' %(d[0],-int(d[1]))
                >>print out[/color]
                >
                > Well, why not the more obvious: s.replace(',',' ,-')[/color]

                But beware negative numbers:
                [color=blue][color=green][color=darkred]
                >>> int("--1")[/color][/color][/color]
                Traceback (most recent call last):
                File "<stdin>", line 1, in ?
                ValueError: invalid literal for int(): --1[color=blue][color=green][color=darkred]
                >>>[/color][/color][/color]

                Therefore at least
                [color=blue][color=green][color=darkred]
                >>> "123,234 567,-789".replace(", ", ",-").replace( "--", "")[/color][/color][/color]
                '123,-234 567,789'[color=blue][color=green][color=darkred]
                >>>[/color][/color][/color]

                As to robustness, the OP relying on commas not being followed by a space
                seems dangerous, too, if the original data is created manually.

                Peter

                Comment

                • Ryan Paul

                  #9
                  Re: list comprehension

                  On Mon, 10 May 2004 12:32:20 +1200, Guy Robinson wrote:
                  [color=blue]
                  > Hello,
                  >
                  > Trying to change a string(x,y values) such as :
                  >
                  > s = "114320,698 08 114272,69920 113568,71600 113328,72272"
                  >
                  > into (x,-y):
                  >
                  > out = "114320,-69808 114272,-69920 113568,-71600 113328,-72272"
                  >
                  > I tried this:
                  >
                  > print [(a[0],-a[1] for a in x.split(',')) for x in e]
                  >
                  > But it doesn't work. Can anyone suggest why or suggest an alternative
                  > way? The text strings are significantly bigger than this so performance
                  > is important.
                  >
                  > TIA,
                  >
                  > Guy[/color]

                  this works:

                  s = "114320,698 08 114272,69920 113568,71600 113328,72272"

                  o = [(int(a[0]),-int(a[1])) for a in [b.split(',') for b in s.split(' ')]]
                  print o

                  [(114320, -69808), (114272, -69920), (113568, -71600), (113328, -72272)]

                  Comment

                  • Guy Robinson

                    #10
                    Re: list comprehension

                    s.replace(',',' ,-') HA!!:-)

                    Thanks Andrew. As usual making it more complicated than it needs to be...

                    Guy

                    Andrew Bennetts wrote:[color=blue]
                    > On Mon, May 10, 2004 at 12:32:20PM +1200, Guy Robinson wrote:
                    >[color=green]
                    >>Hello,
                    >>
                    >>Trying to change a string(x,y values) such as :
                    >>
                    >>s = "114320,698 08 114272,69920 113568,71600 113328,72272"
                    >>
                    >>into (x,-y):
                    >>
                    >>out = "114320,-69808 114272,-69920 113568,-71600 113328,-72272"
                    >>
                    >>I tried this:
                    >>
                    >>print [(a[0],-a[1] for a in x.split(',')) for x in e]
                    >>
                    >>But it doesn't work. Can anyone suggest why or suggest an alternative
                    >>way? The text strings are significantly bigger than this so performance
                    >>is important.[/color]
                    >
                    >
                    > It has several syntax errors; (a[0],-a[1] for a in x.split(',')) is not a
                    > valid expression because list comprehensions are bracketed by square
                    > brackets, not parentheses. Also, the first part of a list comprehension,
                    > the expression to calculate each element, needs to be in parens to if it has
                    > a comma, so that the parser can disambiguate it from an ordinary list.
                    >
                    > I also don't know where you got 'e' from. Is it 's', or 's.split()'?
                    >
                    > If list comprenhensions grow unwieldy, just use a for loop. They're
                    > probably easier to read than a list comprehension that takes you ten minutes
                    > to concoct, and performance is almost identical. For the sake of answering
                    > your question, though, here's a expression that does what you ask:
                    >
                    >[color=green][color=darkred]
                    >>>>s = "114320,698 08 114272,69920 113568,71600 113328,72272"
                    >>>>s.replace(' ,',',-')[/color][/color]
                    >
                    > '114320,-69808 114272,-69920 113568,-71600 113328,-72272'
                    >
                    > You could do this with list comprehensions, e.g.:
                    >
                    >[color=green][color=darkred]
                    >>>>' '.join(['%s,-%s' % tuple(x) for x in [pairs.split(',' ) for pairs in s.split(' ')]])[/color][/color]
                    >
                    > '114320,-69808 114272,-69920 113568,-71600 113328,-72272'
                    >
                    > But I don't really see the point, given the way you've described the
                    > problem.
                    >
                    > -Andrew.
                    >
                    >[/color]

                    Comment

                    • David MacQuigg

                      #11
                      Re: list comprehension

                      On Mon, 10 May 2004 12:32:20 +1200, Guy Robinson
                      <guy@NOSPAM.r-e-d.co.nz> wrote:
                      [color=blue]
                      >Hello,
                      >
                      >Trying to change a string(x,y values) such as :
                      >
                      >s = "114320,698 08 114272,69920 113568,71600 113328,72272"
                      >
                      >into (x,-y):
                      >
                      >out = "114320,-69808 114272,-69920 113568,-71600 113328,-72272"
                      >
                      >I tried this:
                      >
                      >print [(a[0],-a[1] for a in x.split(',')) for x in e]
                      >
                      >But it doesn't work. Can anyone suggest why or suggest an alternative
                      >way? The text strings are significantly bigger than this so performance
                      >is important.[/color]

                      Seems like this is a very common problem, needing to process a
                      substring within a long list of strings. I like the way Ruby handles
                      these problems. Maybe a future version of Python could do this:

                      print s.split(' ').map().split( ',').reflecty() .join(' ')

                      You would need to define the reflecty() function, but the others
                      should be standard. Depending on how much variation you expect in the
                      input data, reflecty() could do whatever checking is necessry to avoid
                      the problems other posters have mentioned. Assuming the inputs are
                      valid string representations of numbers (i.e. no double minuses,
                      etc.), a simple definition could be:

                      def reflecty():
                      x,y = __self__ # a two-string list
                      if y[0] == '-':
                      return [ x, y[1:] ]
                      else:
                      return [ x, '-' + y ]

                      The above syntax is neither Ruby nor Python, but the idea of handling
                      complex sequences of string operations step-by-step, left-to-right was
                      inspired by Ruby. See http://userlinux.com/cgi-bin/wiki.pl?RubyPython
                      for a comparison of Ruby and Python string operations.

                      -- Dave

                      Comment

                      • Christopher Barker

                        #12
                        Re: list comprehension

                        David MacQuigg wrote:[color=blue]
                        > <guy@NOSPAM.r-e-d.co.nz> wrote:[color=green]
                        >>Trying to change a string(x,y values) such as :
                        >>
                        >>s = "114320,698 08 114272,69920 113568,71600 113328,72272"
                        >>
                        >>into (x,-y):
                        >>
                        >>out = "114320,-69808 114272,-69920 113568,-71600 113328,-72272"[/color][/color]

                        if you can count on there being no spaces between the x,y pairs, this works:

                        " ".join([ "%s,%i"%(y[0], -int(y[1]) ) for y in [x.split(",") for x in
                        s.split()] ])

                        Though I don't think I'd do it as a one liner.

                        -Chris


                        --
                        Christopher Barker, Ph.D.
                        Oceanographer

                        NOAA/OR&R/HAZMAT (206) 526-6959 voice
                        7600 Sand Point Way NE (206) 526-6329 fax
                        Seattle, WA 98115 (206) 526-6317 main reception

                        Chris.Barker@no aa.gov

                        Comment

                        Working...