Replace one element of a tuple

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

    #1

    Replace one element of a tuple

    I have an array(?) (sorry, I'm new* to python so I'm probably mangling
    the terminology) that looks like this:

    [((1028L, datetime.dateti me(2006, 5, 30, 7, 0), datetime.dateti me(2006,
    5, 30, 7, 30), 'Arthur', 'Prunella Sees the Light; Return of the
    Snowball', 'Prunella prepares for a sleepover with Marina; D.W. protects
    a snowball.', 'Children', 'tooth.seiner.l an', None, 0L, None, 1L, 1L,
    'Default', 9L, 'SH044107', 'EP0441070123', datetime.dateti me(2006, 5,
    30, 7, 31, 24), 1164179392L, 0.0, 1, datetime.date(2 002, 11, 28), 0, 0L,
    0),), ((1028L, datetime.dateti me(2006, 5, 4, 10, 0),
    datetime.dateti me(2006, 5, 4, 10, 30), 'Bob the Builder', 'Using Clues',
    '', 'Children', 'tooth.seiner.l an', None, 0L, None, 1L, 1L, 'Default',
    6L, 'SH326087', 'EP3260870141', datetime.dateti me(2006, 5, 4, 10, 31,
    30), 1163673536L, 0.0, 1, datetime.date(2 005, 3, 19), 0, 0L, 0),)]

    I want to replace every instance of 'tooth.seiner.l an' with 'localhost'.
    There may be lots and lots of these entries (they're pulled from my
    mythtv database).

    I could brute-force this by rewriting the whole thing and replacing
    every 9th element but there has to be a better way....

    I've looked at various search-and-replace snippets but none that address
    what I am trying to do....

    --Yan

    *I'm not really new to python, just very very rusty. Last time I used
    it was about 3 years ago, and I was equally clueless....
  • akameswaran@gmail.com

    #2
    Re: Replace one element of a tuple


    Captain Dondo wrote:[color=blue]
    > I have an array(?) (sorry, I'm new* to python so I'm probably mangling
    > the terminology) that looks like this:
    >
    > [((1028L, datetime.dateti me(2006, 5, 30, 7, 0), datetime.dateti me(2006,
    > 5, 30, 7, 30), 'Arthur', 'Prunella Sees the Light; Return of the
    > Snowball', 'Prunella prepares for a sleepover with Marina; D.W. protects
    > a snowball.', 'Children', 'tooth.seiner.l an', None, 0L, None, 1L, 1L,
    > 'Default', 9L, 'SH044107', 'EP0441070123', datetime.dateti me(2006, 5,
    > 30, 7, 31, 24), 1164179392L, 0.0, 1, datetime.date(2 002, 11, 28), 0, 0L,
    > 0),), ((1028L, datetime.dateti me(2006, 5, 4, 10, 0),
    > datetime.dateti me(2006, 5, 4, 10, 30), 'Bob the Builder', 'Using Clues',
    > '', 'Children', 'tooth.seiner.l an', None, 0L, None, 1L, 1L, 'Default',
    > 6L, 'SH326087', 'EP3260870141', datetime.dateti me(2006, 5, 4, 10, 31,
    > 30), 1163673536L, 0.0, 1, datetime.date(2 005, 3, 19), 0, 0L, 0),)]
    >
    > I want to replace every instance of 'tooth.seiner.l an' with 'localhost'.
    > There may be lots and lots of these entries (they're pulled from my
    > mythtv database).
    >
    > I could brute-force this by rewriting the whole thing and replacing
    > every 9th element but there has to be a better way....
    >
    > I've looked at various search-and-replace snippets but none that address
    > what I am trying to do....
    >
    > --Yan
    >
    > *I'm not really new to python, just very very rusty. Last time I used
    > it was about 3 years ago, and I was equally clueless....[/color]


    There's a lot of parenthesis :) not easy to read, but unless I'm
    seeing something odd, you have string literals in a tuple. So I don't
    think your going to find a better way than brute force recreation.

    FYI lists are between [] and are mutable
    Tuples are between () and are immutable. If I'm countin paren's right
    you have a list that contains a tuple, that contains another tuple with
    1 element in it.

    so you can recreate the tuples... or convert the whole thing to a list
    of lists.

    Comment

    • BartlebyScrivener

      #3
      Re: Replace one element of a tuple

      >> I've looked at various search-and-replace snippets but none that address[color=blue][color=green]
      >> what I am trying to do....[/color][/color]

      I think you need to tell more about what you're trying to do. You say
      it's in a database? Is that why you can't just put the whole blob in
      your text editor and do search-and-replace?

      And is that also why you can't turn it into a giant string and do
      giantstring.rep lace('unwanted' ,'wanted')

      rd

      Comment

      • Captain Dondo

        #4
        Re: Replace one element of a tuple (LONG)

        BartlebyScriven er wrote:[color=blue][color=green][color=darkred]
        >>>I've looked at various search-and-replace snippets but none that address
        >>>what I am trying to do....[/color][/color]
        >
        >
        > I think you need to tell more about what you're trying to do. You say
        > it's in a database? Is that why you can't just put the whole blob in
        > your text editor and do search-and-replace?
        >
        > And is that also why you can't turn it into a giant string and do
        > giantstring.rep lace('unwanted' ,'wanted')
        >
        > rd
        >[/color]

        Fair enough. I am trying to pull records from one database (on
        tooth.seiner.la n) and create a smaller table with only selected elements
        in another database (on localhost aka hermes).

        My code so far:

        import MySQLdb
        import sys, os, os.path, time, string, dialog

        masterBackend=" tooth.seiner.la n"
        toGoBackend="he rmes.seiner.lan "

        masterDB=MySQLd b.connect(host= masterBackend,u ser="mythtv",pa sswd="mythtv",d b="mythconverg" )

        # pull recordings from masterDB

        c=masterDB.curs or()
        c.execute("""SE LECT title, subtitle, starttime FROM recorded""")

        # build our dialog checkbox

        d = dialog.Dialog(d ialog="dialog")
        d.add_persisten t_args(["--backtitle", "Myth2Go"])

        recordings=[]
        for listing in c.fetchall():
        recordings.appe nd(
        (listing[0]+'|'+listing[2].isoformat(),
        listing[1],0))

        recordings.sort ()

        (retcode, itemlist) = d.checklist(tex t="",
        height=15, width=70, list_height=7,
        choices=recordi ngs,
        title="Which recordings do you want to transfer?")

        selectlist=[]
        for listing in itemlist:
        print listing
        (rectitle, recdate) = listing.split(' |',1)
        c.execute("""SE LECT * FROM recorded WHERE title=%s AND
        starttime=%s""" ,(rectitle,recd ate))
        selectlist.appe nd(c.fetchone() )

        =============== =============== =============== ===========

        The problem is the last line. I am creating a bunch of tuples that are,
        for my purposes, incorrect. I would like to create them with
        masterBackend replaced by toGoBackend.

        Currently (I corrected a small bug based on another post) after a user
        selects what recordings s/he wants, selectlist contains:

        [

        (1028L, datetime.dateti me(2006, 5, 26, 7, 0), datetime.dateti me(2006, 5,
        26, 7, 30), 'Arthur', "What's Cooking?; Buster's Special Delivery", '',
        'Children', 'tooth.seiner.l an', None, 0L, None, 1L, 1L, 'Default', 9L,
        'SH044107', 'EP0441070207', datetime.dateti me(2006, 5, 26, 7, 31, 1),
        1162899392L, 0.0, 0, datetime.date(2 006, 5, 26), 0, 0L, 0),

        (1028L, datetime.dateti me(2006, 5, 27, 9, 0), datetime.dateti me(2006, 5,
        27, 9, 30), 'Arthur', 'Unfinished; D.W., Bossy Boots', '', 'Children',
        'tooth.seiner.l an', None, 0L, None, 1L, 1L, 'Default', 9L, 'SH044107',
        'EP0441070204', datetime.dateti me(2006, 5, 27, 9, 31, 26), 1164783552L,
        0.0, 0, datetime.date(2 006, 5, 23), 0, 0L, 0),

        (1028L, datetime.dateti me(2006, 5, 30, 7, 0), datetime.dateti me(2006, 5,
        30, 7, 30), 'Arthur', 'Prunella Sees the Light; Return of the Snowball',
        'Prunella prepares for a sleepover with Marina; D.W. protects a
        snowball.', 'Children', 'tooth.seiner.l an', None, 0L, None, 1L, 1L,
        'Default', 9L, 'SH044107', 'EP0441070123', datetime.dateti me(2006, 5,
        30, 7, 31, 24), 1164179392L, 0.0, 1, datetime.date(2 002, 11, 28), 0, 0L, 0)

        ]

        which is the correct format to insert into the new database.

        What I'd like to do is build the correct selectlist in the first place,
        rather than build the wrong one and then rebuild a correct one.

        I can't find a replace method that would work on a tuple (not surprising
        since they're immutable) but I also can't find a replace function that
        would replace an element of a tuple and return a new tuple.

        --Yan

        Comment

        • Brian

          #5
          Re: Replace one element of a tuple (LONG)

          Captain Dondo wrote:[color=blue]
          > What I'd like to do is build the correct selectlist in the first place,
          > rather than build the wrong one and then rebuild a correct one.[/color]

          This is sounding more like a SQL/DB problem and less like a Python one.
          If you have a field that is being pulled from the database that you
          would like to do a substitution on, I'm fairly sure MySQL includes a
          CASE statement in their flavor of SQL. Instead of performing a SELECT
          * in your script you could select the individual fields you want, and
          instead of just pulling the problematic column as is, you could pull it
          as something like "select case when sourcehost = x then y else
          sourcehost end case, ...". Naturally if an entire column needs to be
          replaced with a static value, you won't even need to use CASE.

          HTH

          Comment

          • Captain Dondo

            #6
            Re: Replace one element of a tuple (LONG)

            Brian wrote:[color=blue]
            > Captain Dondo wrote:
            >[color=green]
            >>What I'd like to do is build the correct selectlist in the first place,
            >>rather than build the wrong one and then rebuild a correct one.[/color]
            >
            >
            > This is sounding more like a SQL/DB problem and less like a Python one.
            > If you have a field that is being pulled from the database that you
            > would like to do a substitution on, I'm fairly sure MySQL includes a
            > CASE statement in their flavor of SQL. Instead of performing a SELECT
            > * in your script you could select the individual fields you want, and
            > instead of just pulling the problematic column as is, you could pull it
            > as something like "select case when sourcehost = x then y else
            > sourcehost end case, ...". Naturally if an entire column needs to be
            > replaced with a static value, you won't even need to use CASE.
            >[/color]

            AFAICT, that one column is always the same, the name of the host that
            the database resides on. As myth can use multiple backends , it sort of
            makes sense, but it seems redunandant to me. Even with mutliple
            backends, I would hope you have a single database....

            I thought about just picking all the other fields via the SQL query, but
            this seemed simpler to me....

            Anyway, here's the code I came up with:

            for listing in itemlist:
            (rectitle, recdate) = listing.split(' |',1)
            c.execute("""SE LECT * FROM recorded WHERE title=%s AND
            starttime=%s""" ,(rectitle,recd ate))
            for listitem in c.fetchall():
            if 'tooth.seiner.l an' in listitem:
            selectlist.appe nd(listitem[:7] +
            ('hermes.seiner .lan',) + listitem[9:])
            else:
            selectlist.appe nd(listitem)

            Comment

            • BartlebyScrivener

              #7
              Re: Replace one element of a tuple (LONG)

              >> that one column is always the same, the name of the host that[color=blue][color=green]
              >> the database resides on.[/color][/color]

              Then why are you pulling all of the other stuff out of the db? Why
              don't you just

              UPDATE tablename
              SET hostname(or colname) = 'localhost'
              WHERE search condition = the rows you want to change

              Comment

              • Captain Dondo

                #8
                Re: Replace one element of a tuple (LONG)

                BartlebyScriven er wrote:[color=blue][color=green][color=darkred]
                >>>that one column is always the same, the name of the host that
                >>>the database resides on.[/color][/color]
                >
                >
                > Then why are you pulling all of the other stuff out of the db? Why
                > don't you just
                >
                > UPDATE tablename
                > SET hostname(or colname) = 'localhost'
                > WHERE search condition = the rows you want to change
                >[/color]

                Well, there is an interactive dialog where the user picks which records
                s/he wants to put into the other database. So in the target database,
                that table may not even exist until the user selects which records go in
                there.

                But it does sound like I need to do some work on the database query.... :-)

                --Yan

                Comment

                • Bruno Desthuilliers

                  #9
                  Re: Replace one element of a tuple (LONG)

                  Captain Dondo a écrit :
                  (snip)
                  [color=blue]
                  > c=masterDB.curs or()
                  > c.execute("""SE LECT title, subtitle, starttime FROM recorded""")
                  >
                  > # build our dialog checkbox
                  >
                  > d = dialog.Dialog(d ialog="dialog")
                  > d.add_persisten t_args(["--backtitle", "Myth2Go"])
                  >
                  > recordings=[]
                  > for listing in c.fetchall():
                  > recordings.appe nd(
                  > (listing[0]+'|'+listing[2].isoformat(),
                  > listing[1],0))
                  >
                  > recordings.sort ()[/color]

                  Why don't you just add an order by clause in your sql statement ???
                  [color=blue]
                  > (retcode, itemlist) = d.checklist(tex t="",
                  > height=15, width=70, list_height=7,
                  > choices=recordi ngs,
                  > title="Which recordings do you want to transfer?")
                  >
                  > selectlist=[]
                  > for listing in itemlist:
                  > print listing
                  > (rectitle, recdate) = listing.split(' |',1)
                  > c.execute("""SE LECT * FROM recorded WHERE title=%s AND
                  > starttime=%s""" ,(rectitle,recd ate))[/color]

                  is the combination of title and starttime a unique key ?

                  Also, unless you have lots of records with huge blobs in 'recorded'
                  table, this smells like a WTF.
                  [color=blue]
                  > selectlist.appe nd(c.fetchone() )[/color]

                  [color=blue]
                  > The problem is the last line.[/color]

                  I'm afraid this is not the only problem...
                  [color=blue]
                  > I am creating a bunch of tuples that are,
                  > for my purposes, incorrect.[/color]

                  selectlist.appe nd(list(c.fetch one)) would create a bunch of lists instead.
                  [color=blue]
                  > I would like to create them with
                  > masterBackend replaced by toGoBackend.
                  >
                  > Currently (I corrected a small bug based on another post) after a user
                  > selects what recordings s/he wants, selectlist contains:
                  >
                  > [
                  >
                  > (1028L, datetime.dateti me(2006, 5, 26, 7, 0), datetime.dateti me(2006, 5,
                  > 26, 7, 30), 'Arthur', "What's Cooking?; Buster's Special Delivery", '',
                  > 'Children', 'tooth.seiner.l an', None, 0L, None, 1L, 1L, 'Default', 9L,
                  > 'SH044107', 'EP0441070207', datetime.dateti me(2006, 5, 26, 7, 31, 1),
                  > 1162899392L, 0.0, 0, datetime.date(2 006, 5, 26), 0, 0L, 0),[/color]

                  No huge blob in sight. And since the list of records fits on a dialog
                  with checkboxes, I think you could easily avoid querying the DB that
                  many times. FWIW, you could probably query it once only.
                  [color=blue]
                  > (1028L, datetime.dateti me(2006, 5, 27, 9, 0), datetime.dateti me(2006, 5,
                  > 27, 9, 30), 'Arthur', 'Unfinished; D.W., Bossy Boots', '', 'Children',
                  > 'tooth.seiner.l an', None, 0L, None, 1L, 1L, 'Default', 9L, 'SH044107',
                  > 'EP0441070204', datetime.dateti me(2006, 5, 27, 9, 31, 26), 1164783552L,
                  > 0.0, 0, datetime.date(2 006, 5, 23), 0, 0L, 0),
                  >
                  > (1028L, datetime.dateti me(2006, 5, 30, 7, 0), datetime.dateti me(2006, 5,
                  > 30, 7, 30), 'Arthur', 'Prunella Sees the Light; Return of the Snowball',
                  > 'Prunella prepares for a sleepover with Marina; D.W. protects a
                  > snowball.', 'Children', 'tooth.seiner.l an', None, 0L, None, 1L, 1L,
                  > 'Default', 9L, 'SH044107', 'EP0441070123', datetime.dateti me(2006, 5,
                  > 30, 7, 31, 24), 1164179392L, 0.0, 1, datetime.date(2 002, 11, 28), 0, 0L, 0)
                  >
                  > ]
                  >
                  > which is the correct format to insert into the new database.
                  >
                  > What I'd like to do is build the correct selectlist in the first place,
                  > rather than build the wrong one and then rebuild a correct one.
                  >
                  > I can't find a replace method that would work on a tuple (not surprising
                  > since they're immutable) but I also can't find a replace function that
                  > would replace an element of a tuple and return a new tuple.[/color]

                  You can of course turn a tuple into a list, then modify the list. But it
                  would still be a waste of time. Learning the full syntax for a SQL
                  select might be more useful. You can do something like:

                  select item1, item2, 'someconstant', item3, ..., from sometable (...)

                  which avoid having anything to replace.


                  Assuming that title + starttime is the primary key, and - not knowing
                  the structure of your table - assuming that starttime is the second
                  field, title the 5th and subtitle the 6th :

                  # ---------------------
                  sql = """
                  SELECT f1, starttime, f3, f4, title, subtitle, f7, '%s', f9,
                  (..etc...), f24
                  FROM recorded
                  ORDER BY title, starttime
                  """ % toGoBackend

                  c.execute(sql)
                  rows = c.fetchall()
                  # seems like dialog.checklis t wants strings as tags
                  # tried with ints, but it crashed...
                  choices = [(str(i), row[5], 0) for row in rows]
                  d = dialog.Dialog(d ialog="dialog")
                  d.add_persisten t_args(["--backtitle", "Myth2Go"])
                  retcode, indices = d.checklist('', choices=choices )
                  if retcode:
                  # exit or return

                  selectlist = [rows[i] for i in map(int, indices)]
                  # ---------------------



                  HTH

                  Comment

                  Working...