Replace one element of a tuple

C

Captain Dondo

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

[((1028L, datetime.datetime(2006, 5, 30, 7, 0), datetime.datetime(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.lan', None, 0L, None, 1L, 1L,
'Default', 9L, 'SH044107', 'EP0441070123', datetime.datetime(2006, 5,
30, 7, 31, 24), 1164179392L, 0.0, 1, datetime.date(2002, 11, 28), 0, 0L,
0),), ((1028L, datetime.datetime(2006, 5, 4, 10, 0),
datetime.datetime(2006, 5, 4, 10, 30), 'Bob the Builder', 'Using Clues',
'', 'Children', 'tooth.seiner.lan', None, 0L, None, 1L, 1L, 'Default',
6L, 'SH326087', 'EP3260870141', datetime.datetime(2006, 5, 4, 10, 31,
30), 1163673536L, 0.0, 1, datetime.date(2005, 3, 19), 0, 0L, 0),)]

I want to replace every instance of 'tooth.seiner.lan' 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....
 
A

akameswaran

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

[((1028L, datetime.datetime(2006, 5, 30, 7, 0), datetime.datetime(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.lan', None, 0L, None, 1L, 1L,
'Default', 9L, 'SH044107', 'EP0441070123', datetime.datetime(2006, 5,
30, 7, 31, 24), 1164179392L, 0.0, 1, datetime.date(2002, 11, 28), 0, 0L,
0),), ((1028L, datetime.datetime(2006, 5, 4, 10, 0),
datetime.datetime(2006, 5, 4, 10, 30), 'Bob the Builder', 'Using Clues',
'', 'Children', 'tooth.seiner.lan', None, 0L, None, 1L, 1L, 'Default',
6L, 'SH326087', 'EP3260870141', datetime.datetime(2006, 5, 4, 10, 31,
30), 1163673536L, 0.0, 1, datetime.date(2005, 3, 19), 0, 0L, 0),)]

I want to replace every instance of 'tooth.seiner.lan' 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....


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.
 
B

BartlebyScrivener

I've looked at various search-and-replace snippets but none that address
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.replace('unwanted','wanted')

rd
 
C

Captain Dondo

BartlebyScrivener said:
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.replace('unwanted','wanted')

rd

Fair enough. I am trying to pull records from one database (on
tooth.seiner.lan) 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.lan"
toGoBackend="hermes.seiner.lan"

masterDB=MySQLdb.connect(host=masterBackend,user="mythtv",passwd="mythtv",db="mythconverg")

# pull recordings from masterDB

c=masterDB.cursor()
c.execute("""SELECT title, subtitle, starttime FROM recorded""")

# build our dialog checkbox

d = dialog.Dialog(dialog="dialog")
d.add_persistent_args(["--backtitle", "Myth2Go"])

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

recordings.sort()

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

selectlist=[]
for listing in itemlist:
print listing
(rectitle, recdate) = listing.split('|',1)
c.execute("""SELECT * FROM recorded WHERE title=%s AND
starttime=%s""",(rectitle,recdate))
selectlist.append(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.datetime(2006, 5, 26, 7, 0), datetime.datetime(2006, 5,
26, 7, 30), 'Arthur', "What's Cooking?; Buster's Special Delivery", '',
'Children', 'tooth.seiner.lan', None, 0L, None, 1L, 1L, 'Default', 9L,
'SH044107', 'EP0441070207', datetime.datetime(2006, 5, 26, 7, 31, 1),
1162899392L, 0.0, 0, datetime.date(2006, 5, 26), 0, 0L, 0),

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

(1028L, datetime.datetime(2006, 5, 30, 7, 0), datetime.datetime(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.lan', None, 0L, None, 1L, 1L,
'Default', 9L, 'SH044107', 'EP0441070123', datetime.datetime(2006, 5,
30, 7, 31, 24), 1164179392L, 0.0, 1, datetime.date(2002, 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
 
B

Brian

Captain said:
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.

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
 
C

Captain Dondo

Brian said:
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.

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("""SELECT * FROM recorded WHERE title=%s AND
starttime=%s""",(rectitle,recdate))
for listitem in c.fetchall():
if 'tooth.seiner.lan' in listitem:
selectlist.append(listitem[:7] +
('hermes.seiner.lan',) + listitem[9:])
else:
selectlist.append(listitem)
 
B

BartlebyScrivener

that one column is always the same, the name of the host that
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
 
C

Captain Dondo

BartlebyScrivener said:
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

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
 
B

Bruno Desthuilliers

Captain Dondo a écrit :
(snip)
c=masterDB.cursor()
c.execute("""SELECT title, subtitle, starttime FROM recorded""")

# build our dialog checkbox

d = dialog.Dialog(dialog="dialog")
d.add_persistent_args(["--backtitle", "Myth2Go"])

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

Why don't you just add an order by clause in your sql statement ???
(retcode, itemlist) = d.checklist(text="",
height=15, width=70, list_height=7,
choices=recordings,
title="Which recordings do you want to transfer?")

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

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.
selectlist.append(c.fetchone())

The problem is the last line.

I'm afraid this is not the only problem...
I am creating a bunch of tuples that are,
for my purposes, incorrect.

selectlist.append(list(c.fetchone)) would create a bunch of lists instead.
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.datetime(2006, 5, 26, 7, 0), datetime.datetime(2006, 5,
26, 7, 30), 'Arthur', "What's Cooking?; Buster's Special Delivery", '',
'Children', 'tooth.seiner.lan', None, 0L, None, 1L, 1L, 'Default', 9L,
'SH044107', 'EP0441070207', datetime.datetime(2006, 5, 26, 7, 31, 1),
1162899392L, 0.0, 0, datetime.date(2006, 5, 26), 0, 0L, 0),

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.
(1028L, datetime.datetime(2006, 5, 27, 9, 0), datetime.datetime(2006, 5,
27, 9, 30), 'Arthur', 'Unfinished; D.W., Bossy Boots', '', 'Children',
'tooth.seiner.lan', None, 0L, None, 1L, 1L, 'Default', 9L, 'SH044107',
'EP0441070204', datetime.datetime(2006, 5, 27, 9, 31, 26), 1164783552L,
0.0, 0, datetime.date(2006, 5, 23), 0, 0L, 0),

(1028L, datetime.datetime(2006, 5, 30, 7, 0), datetime.datetime(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.lan', None, 0L, None, 1L, 1L,
'Default', 9L, 'SH044107', 'EP0441070123', datetime.datetime(2006, 5,
30, 7, 31, 24), 1164179392L, 0.0, 1, datetime.date(2002, 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.

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.checklist wants strings as tags
# tried with ints, but it crashed...
choices = [(str(i), row[5], 0) for row in rows]
d = dialog.Dialog(dialog="dialog")
d.add_persistent_args(["--backtitle", "Myth2Go"])
retcode, indices = d.checklist('', choices=choices)
if retcode:
# exit or return

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



HTH
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,297
Messages
2,571,536
Members
48,282
Latest member
Xyprime

Latest Threads

Top