d2jsp
Log InRegister
d2jsp Forums > Off-Topic > Computers & IT > Programming & Development > Python >.< > Nested Lists
Add Reply New Topic New Poll
Member
Posts: 62,215
Joined: Jun 3 2007
Gold: 9,039.20
May 10 2014 10:56pm
I have varying number of lists within lists, each list contains two elements.

Structured like this:

Code
[[Name or Email], [Line of Text],
[Name or Email], [Line of Text],
[Name or Email], [Line of Text],
[Name or Email], [Line of Text],
[Name or Email], [Line of Text]]


I am interested in a method of looping through the lists, checking the first element and either changing the element to another name based, having the value stay consistent for each element.

If the name is "Jacob" then it would it would say "Tom" or another random voice from the six I have in in the pool for for each unique name, I am wondering if I should use numbers then relate each unique name to this number or just directly replace the name(s) and emails with the system voices.

I cannot think of a good method to do the replacement, nested lists are not fun.

Sorry, I am really bad at this but I'll show you the functions I use the generate this data and the other functions I have that generate the other names from a pool of available system voices.

Code
def assign_voice(user_data):
""" Assign Random System-Voice to User(s) """
data = user_data
voice_list = ['Agnes', 'Alex', 'Bruce', 'Junior', 'Fred', 'Tom']
shuffle(voice_list)
users = list(data[2]) # list of all users
new_voice_list = voice_list[0:len(users)] # list first two from random-shuffled voice-pool
return dict(zip(users, new_voice_list)) # return dictionary of {user:voice} - {k:v}


Code
def regex_line(data):
""" Create Tuple of Lists ([User, Line-of-Text])

SAMPLE OUTPUT:

[(Name or Email), (Line of Text),
(Name or Email), (Line of Text),
(Name or Emall), (Line of Text),
(Name or Email), (Line of Text),
(Name or Email), (Line of Text),]

"""
string = data
pattern = re.compile("^\d?\d:\d\d:\d\d\s(.*): (.*)\n", re.IGNORECASE|re.MULTILINE)
user = pattern.findall(string)
using = user
set_users = list(set(using))
number = len(using) # determine number of users
unum_users = len(set(using)) # determine number of unique users
return user


Code
def regex_users(data):
""" Determine User Number """
string = data
pattern = re.compile("\d?\d:\d\d\s(.*):", re.IGNORECASE|re.MULTILINE)
users = pattern.findall(string)
set_users = list(set(users))
number = len(users) # determine number of users
unum_users = len(set(users)) # determine number of unique users
return number, unum_users, set_users # tuple



Code
data = open_transcript()
user_data = regex_users(data) # occurrence of data, number of users, list of user(s)
user_line = regex_line(data) # [(User, Line of Data)]
user_line = list(list(e) for e in user_line) #convert Tuples to Lists [(), ()] -> [[], []]
user_dict = assign_voice(user_data) # dictionary of {user:voice} - {k:v}


What I hope to eventually output the captured text using a system voice, a unique system voice for each user.

Code
def say(v, t):
""" Output System Sound say(Voice, Text) """
os.system('say -v '+v+' '+t)


I also have system voice functions written out for each voice, if it comes to that:

Code
def tm(t):
""" Output Sound Tom(Text) """
os.system('say -v Tom '+t)


Anyone good with lists?

This post was edited by killg0re on May 10 2014 11:00pm
Member
Posts: 62,215
Joined: Jun 3 2007
Gold: 9,039.20
May 11 2014 06:02am
Derp, didn't think it would be so easy, just two for loops.
Member
Posts: 62,215
Joined: Jun 3 2007
Gold: 9,039.20
May 12 2014 03:25am
This is similar to what I decided on while testing:

Code
nesty = [['List'], ['Text spam, text heh'], ['List'], ['Heh, ye okay'], ['email@domain.com']]

name = 'List'
email = 'email@domain.com'
voice = 'Tom'
voice_two = 'Agnes'

def find_replace(nesty):
for l in nesty:
if name in l[0]:
l[0] = voice
if email in l[0]:
l[0] = voice_two

return nesty



Err, let me know if there's a more pythonic way of doing it and I'll see what works, but I think this will be okay for now. :ph34r:

Member
Posts: 582
Joined: Mar 22 2014
Gold: 0.00
May 12 2014 07:38pm
Code
replacement = {name:voice, email:voice_two}
def find_replace(nesty, replacement):
return map(lambda x: [replacement.get(x[0], x[0])] + x[1:], nesty)



Code
def find_replace(nesty, replacement):
for l in nesty:
l[0] = replacement.get(l[0], l[0])
return nesty


This post was edited by poodaH on May 12 2014 07:47pm
Member
Posts: 62,215
Joined: Jun 3 2007
Gold: 9,039.20
May 13 2014 09:17am
Quote (poodaH @ May 12 2014 07:38pm)
Code
replacement = {name:voice, email:voice_two}
def find_replace(nesty, replacement):
    return map(lambda x: [replacement.get(x[0], x[0])] + x[1:], nesty)



Code
def find_replace(nesty, replacement):
    for l in nesty:
        l[0] = replacement.get(l[0], l[0])
    return nesty


Both of these are awesome.

I made another short function to the user and text into separate list, groups of two:

Code
def group(lust):
lust = [lust[e:e+2] for e in xrange(0, len(lust), 2)]
return lust


Member
Posts: 62,215
Joined: Jun 3 2007
Gold: 9,039.20
May 14 2014 10:57am
welp, I finished this, it outputs okay and supports up to 6 unique voices.

I'm not going to post the code but most of it is here already and I'm sure anyone here could do it in their sleep and its OS X only.

I re-wrote this:

Code
def say(v, t):
""" Output System Sound say(Voice, Text) """
os.system('say -v '+v+' '+t)


to this:

Code
def say_list(input_list):
""" ['Voice', 'Text'] through os.system() """
v = input_list[0]
t = input_list[1]
system('say -v '+v+' '+str(repr(t)))


which works effectively the same as this complicated mess:

Code
def subprocess_say(input_list):
""" ['Voice', 'Text'] through subprocess..."""
FNULL = open(devnull, 'w')
retcode = call(['say', '-v', input_list[0], input_list[1]], stdout=FNULL, stderr=STDOUT)


:drool:

This post was edited by killg0re on May 14 2014 11:00am
Go Back To Programming & Development Topic List
Add Reply New Topic New Poll