Using reverse iteration to clean up a list

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

    Using reverse iteration to clean up a list

    I have list of lists of the following form

    L=[['A', 100], ['B', 300], ['A', 400], ['B', -100]]

    I want to aggregate these lists, i.e. to reduce L to
    L=[['A', 500], ['B', 200]] #500 = 100+400, 200=300-100

    Here's how I have done it:
    L.sort()
    for i in range(len(L),0,-1):
    if L[i-1][0]=L[i][0]:
    L[i-1][2] += L[i][2]
    del L[i]

    Is there a simpler way to do this using the new reverse iteration
    facility in Python 2.4?

    Thomas Philips

  • Paul Rubin

    #2
    Re: Using reverse iteration to clean up a list

    tkpmep@hotmail. com writes:[color=blue]
    > I have list of lists of the following form
    >
    > L=[['A', 100], ['B', 300], ['A', 400], ['B', -100]]
    >
    > I want to aggregate these lists, i.e. to reduce L to
    > L=[['A', 500], ['B', 200]] #500 = 100+400, 200=300-100[/color]

    How about:

    v = {}
    for name,val in L:
    v[name] = v.get(name, 0) + val
    L = v.items()

    Comment

    • John Machin

      #3
      Re: Using reverse iteration to clean up a list


      Paul Rubin wrote:[color=blue]
      > tkpmep@hotmail. com writes:[color=green]
      > > I have list of lists of the following form
      > >
      > > L=[['A', 100], ['B', 300], ['A', 400], ['B', -100]]
      > >
      > > I want to aggregate these lists, i.e. to reduce L to
      > > L=[['A', 500], ['B', 200]] #500 = 100+400, 200=300-100[/color]
      >
      > How about:
      >
      > v = {}
      > for name,val in L:
      > v[name] = v.get(name, 0) + val
      > L = v.items()[/color]

      Followed by L.sort() if the OP really needs his list sorted.
      Alternatively, he may prefer to leave it in a dict; in fact, if he had
      been using a dict all along and maintaining it on the fly by "v[name]
      = v.get(name, 0) + val", he wouldn't need to batch-fix his data
      structure now.

      tkpmep, how did you get this list of lists with duplicate keys and
      additive values? What do you want to do with it next?

      Comment

      • Luis M. Gonzalez

        #4
        Re: Using reverse iteration to clean up a list

        Well, I'm not sure if this is what you want, but you could use a
        dictionary:
        [color=blue][color=green][color=darkred]
        >>> d={}
        >>> for i,e in L:[/color][/color][/color]
        if d.has_key(i):
        d[i] += e
        else:
        d[i] = e

        [color=blue][color=green][color=darkred]
        >>> d[/color][/color][/color]
        {'A': 500, 'B': 200}[color=blue][color=green][color=darkred]
        >>>[/color][/color][/color]

        Comment

        • Michael Hoffman

          #5
          Re: Using reverse iteration to clean up a list

          tkpmep@hotmail. com wrote:
          [color=blue]
          > L=[['A', 100], ['B', 300], ['A', 400], ['B', -100]]
          >
          > I want to aggregate these lists, i.e. to reduce L to
          > L=[['A', 500], ['B', 200]] #500 = 100+400, 200=300-100[/color]

          """
          from itertools import groupby
          from operator import itemgetter

          [(key, sum(item[1] for item in sublist))
          for key, sublist
          in groupby(sorted( L, key=itemgetter( 0)), itemgetter(0))]
          """

          OK, strictly speaking that will get you a list of tuples
          instead of a list of lists, but that's easy enough to fix
          if you insist on a list of lists. Tuples are generally used
          for heterogeneous fixed-length sequences.
          --
          Michael Hoffman

          Comment

          • tkpmep@hotmail.com

            #6
            Re: Using reverse iteration to clean up a list

            Thank you all so much for the generous dollop of help: the dictionary
            suggestion is particularly helpful. The problem arises as follows: A
            software application stores the securities held in a portfolio in a
            ..csv file, one row per security, with three colulmns.

            The first has a security identifier or descriptor (such as a ticker)
            the second has a single letter that identifies the type of the
            identifier (T for ticker, C for cusip etc.) and the third has the
            number of shares. A typical line looks like this:

            IBM, T, 500

            I need to read in one or more portfolios and aggregate their holdings.
            To do so, I read in the portfolios using the csv package, convert each
            line to a list and then append it to a list of lists. Eventually the
            list of lists contains all the securities, and can then be sorted and
            aggregated.

            I suppose I could convert it instead to a dictionary, and the most
            natural key would be the first two items, i.e. a portfolio containing
            just 500 shares of IBM ought to be represented as
            {("IBM", "T") : 500 }

            How can I translate the data I read in using csv.reader into a
            dictionary?

            Thomas Philips

            Comment

            • Michael Hoffman

              #7
              Re: Using reverse iteration to clean up a list

              tkpmep@hotmail. com wrote:[color=blue]
              > Thank you all so much for the generous dollop of help: the dictionary
              > suggestion is particularly helpful. The problem arises as follows: A
              > software application stores the securities held in a portfolio in a
              > .csv file, one row per security, with three colulmns.
              >
              > The first has a security identifier or descriptor (such as a ticker)
              > the second has a single letter that identifies the type of the
              > identifier (T for ticker, C for cusip etc.) and the third has the
              > number of shares. A typical line looks like this:
              >
              > IBM, T, 500
              >
              > I need to read in one or more portfolios and aggregate their holdings.
              > To do so, I read in the portfolios using the csv package, convert each
              > line to a list and then append it to a list of lists. Eventually the
              > list of lists contains all the securities, and can then be sorted and
              > aggregated.
              >
              > I suppose I could convert it instead to a dictionary, and the most
              > natural key would be the first two items, i.e. a portfolio containing
              > just 500 shares of IBM ought to be represented as
              > {("IBM", "T") : 500 }
              >
              > How can I translate the data I read in using csv.reader into a
              > dictionary?[/color]

              portfolio = {}

              for row in csv.reader(infi le):
              key = tuple(row[:2])

              portfolio[key] = portfolio.get(k ey, 0) + int(row[2])

              You could also do a groupby solution with
              itemgetter(slic e(0, 2))--thanks to Steven Bethard for recently
              pointing out the possibility here of doing that. I'd go with the
              dict for this application though.
              --
              Michael Hoffman

              Comment

              Working...