Jump to content

Python Help

namarino

Hey guys, I'm working with dictionaries right now for an assignment. They are in the form of {(name, gender): {year: (count, rank)}}. Basically this function that I'm working on changes the rank according to the count. I know how to read the dictionary but how do compare the count with the count in other dictionaries and assign a rank? Hope that makes sense. Thanks!

Link to comment
Share on other sites

Link to post
Share on other sites

What exactly is the assignment?  It would help to know more about the problem to give better advice about how to tackle it.  E.g., do you have multiple sets of year/count/rank for each person?  What are you trying to do with this data?  Do you need to use dictionaries, or is that just the approach you chose?  What is the data you're using?

 

A quick note: it looks like you're effectively trying to create a database containing a name, a gender, and a year (or multiple years?) with corresponding count and rank values.  There are much more effective ways to do a database than a convoluted dictionary, e.g. using classes.

 

What I can answer, though, from what you've given: you have (count, rank) as a tuple, and you can't modify individual elements inside of a tuple in Python.  You'd have to re-assign the entire tuple at once.  While that's doable, it's a bit less clean to me than, say, storing the count and rank values in a list--[count, rank]--and then modifying each item directly.  (so, year:[count, rank] rather than year:(count, rank)).

 

To compare and assign items in the dictionary you have set up, just do something like this:

# foo and bar are dictionaries with the setup your described in the first post# Check if the count values are the same (putting in some made-up values)if foo[('bob', 'm')][1999][0] == bar[('jane', 'f')][1997][0]:    do something# Assigning a rank--leaving (count, rank) as a tupletemp = list(foo[('bob', 'm')][1999])temp[1] = 'new rank'foo[('bob', 'm')][1999] = list(temp)# Assigning a rank, if you have the count and rank values in a list: [count, rank]foo[('bob', 'm')][1999][1] = 'new rank'

Your current dictionary setup seems really weird to me.  It seems like it would be much more natural to do something like {name:{gender:gender, {year1:[count, rank], year2:[count, rank], ...}}}, but even then, that's weird to read.  There's got to be a better way to store the data you want than like this.

 

I can give you some more specific tips if you give more information on the assignment and what exactly you're doing.  Because this looks like a problem that could be a lot cleaner and clearer if you use classes rather than dictionaries, and might have some other things that can make your life a lot easier, but I would need to know more about the problem first.

Link to comment
Share on other sites

Link to post
Share on other sites

What exactly is the assignment?  It would help to know more about the problem to give better advice about how to tackle it.  E.g., do you have multiple sets of year/count/rank for each person?  What are you trying to do with this data?  Do you need to use dictionaries, or is that just the approach you chose?  What is the data you're using?

 

A quick note: it looks like you're effectively trying to create a database containing a name, a gender, and a year (or multiple years?) with corresponding count and rank values.  There are much more effective ways to do a database than a convoluted dictionary, e.g. using classes.

 

What I can answer, though, from what you've given: you have (count, rank) as a tuple, and you can't modify individual elements inside of a tuple in Python.  You'd have to re-assign the entire tuple at once.  While that's doable, it's a bit less clean to me than, say, storing the count and rank values in a list--[count, rank]--and then modifying each item directly.  (so, year:[count, rank] rather than year:(count, rank)).

 

To compare and assign items in the dictionary you have set up, just do something like this:

# foo and bar are dictionaries with the setup your described in the first post# Check if the count values are the same (putting in some made-up values)if foo[('bob', 'm')][1999][0] == bar[('jane', 'f')][1997][0]:    do something# Assigning a rank--leaving (count, rank) as a tupletemp = list(foo[('bob', 'm')][1999])temp[1] = 'new rank'foo[('bob', 'm')][1999] = list(temp)# Assigning a rank, if you have the count and rank values in a list: [count, rank]foo[('bob', 'm')][1999][1] = 'new rank'

Your current dictionary setup seems really weird to me.  It seems like it would be much more natural to do something like {name:{gender:gender, {year1:[count, rank], year2:[count, rank], ...}}}, but even then, that's weird to read.  There's got to be a better way to store the data you want than like this.

 

I can give you some more specific tips if you give more information on the assignment and what exactly you're doing.  Because this looks like a problem that could be a lot cleaner and clearer if you use classes rather than dictionaries, and might have some other things that can make your life a lot easier, but I would need to know more about the problem first.

Haha believe me, I know. This is an assignment for school and we have to read through that database in this particular function. The database has to be organized like that unfortunately. I did figure it out though (it only took the entire day). I have one question for you though. I have a list of tuples written like this [((name, gender), count)), ((name, gender), count))]. I basically want to take the elements out of each member. So (name, gender) and then count. I can't seem to figure out how to do that though. Any suggestions??

Link to comment
Share on other sites

Link to post
Share on other sites

Haha believe me, I know. This is an assignment for school and we have to read through that database in this particular function. The database has to be organized like that unfortunately. I did figure it out though (it only took the entire day). I have one question for you though. I have a list of tuples written like this [((name, gender), count)), ((name, gender), count))]. I basically want to take the elements out of each member. So (name, gender) and then count. I can't seem to figure out how to do that though. Any suggestions??

Well, whoever organized your database did a super weird job of it.

 

As for splitting up tuples of tuples: You can index tuples just like lists.  So, if you have x = ((name, gender), count), you can do x[0] to get (name, gender) (and then x[0][0] and x[0][1] to get name and gender, respectively) and x[1] to get count.  You can use this to do whatever comparisons or math you need to, but remember, if you want to re-define any values in x, you need to redefine the entire tuple at once.  BUT, you can take the indexed elements out of the tuples and store them in variables or lists or the like somewhere else.  So you could make a list of all name values, a list of all gender values, etc by just indexing the item in a tuple and adding it to the respective list.

 

If you have a list of these tuples (like in your post) and want to get some value out, it'll look something like this:

x = [((name1, gender1), count1), ((name2, gender2), count2)]# Indexes gender1.x[0][0][1]# Indexes name2x[1][0][0]# Indexes count1x[0][1]# This won't work--can't re-define just one element of a tuplex[i][0][1] = 'f'# This will work--you have to redefine the entire tuple at the same timex[i] = ((name_i, gender_i), count_i)
Link to comment
Share on other sites

Link to post
Share on other sites

 

Well, whoever organized your database did a super weird job of it.

 

As for splitting up tuples of tuples: You can index tuples just like lists.  So, if you have x = ((name, gender), count), you can do x[0] to get (name, gender) (and then x[0][0] and x[0][1] to get name and gender, respectively) and x[1] to get count.  You can use this to do whatever comparisons or math you need to, but remember, if you want to re-define any values in x, you need to redefine the entire tuple at once.  BUT, you can take the indexed elements out of the tuples and store them in variables or lists or the like somewhere else.  So you could make a list of all name values, a list of all gender values, etc by just indexing the item in a tuple and adding it to the respective list.

 

If you have a list of these tuples (like in your post) and want to get some value out, it'll look something like this:

x = [((name1, gender1), count1), ((name2, gender2), count2)]# Indexes gender1.x[0][0][1]# Indexes name2x[1][0][0]# Indexes count1x[0][1]# This won't work--can't re-define just one element of a tuplex[i][0][1] = 'f'# This will work--you have to redefine the entire tuple at the same timex[i] = ((name_i, gender_i), count_i)

So how would I construct a for loop with that notion? Basically what I want to do is take those two values, (name, gender) and count and use it to change the the values in the dictionaries.

Link to comment
Share on other sites

Link to post
Share on other sites

So how would I construct a for loop with that notion? Basically what I want to do is take those two values, (name, gender) and count and use it to change the the values in the dictionaries.

I'm not 100% sure what you mean, but I think something like this: you can use x[0] to get (name, gender) for the ith item in x (your list of ((name, gender), count) tuples).  You can use this as the key to look up some entry in your dictionary (so, if your dictionary is foo, something like foo[x[0]] to get that person's entry).  Then you can compare x[1], the count value, to the count value in that dictionary entry using normal indexing, and have your function re-assign the whole (count, rank) tuple in the dictionary if it needs to change.

Link to comment
Share on other sites

Link to post
Share on other sites

I'm not 100% sure what you mean, but I think something like this: you can use x[0] to get (name, gender) for the ith item in x (your list of ((name, gender), count) tuples).  You can use this as the key to look up some entry in your dictionary (so, if your dictionary is foo, something like foo[x[0]] to get that person's entry).  Then you can compare x[1], the count value, to the count value in that dictionary entry using normal indexing, and have your function re-assign the whole (count, rank) tuple in the dictionary if it needs to change.

Yeah that's essentially what I'm going to be dong. So basically with the for loop I want to say this:

#for loop    #for loop        #grab first element of tuple(name, gender)        #grab second element of tuple (count)        #update value of original dictionary    

Does that make any more sense??? Sorry if I didn't explain it too well.

Link to comment
Share on other sites

Link to post
Share on other sites

Yeah that's essentially what I'm going to be dong. So basically with the for loop I want to say this:

#for loop    #for loop        #grab first element of tuple(name, gender)        #grab second element of tuple (count)        #update value of original dictionary    

Does that make any more sense??? Sorry if I didn't explain it too well.

Could you post the actual Python code you're trying?  I don't know if you'd need two for loops, but otherwise that does look like the sort of scheme you'd want to use.

Link to comment
Share on other sites

Link to post
Share on other sites

Could you post the actual Python code you're trying?  I don't know if you'd need two for loops, but otherwise that does look like the sort of scheme you'd want to use.

for x in range(len(sub_db)):        for y in range(len(sub_db[x])):            #Here I basically want to take the (name, gender) and count simultaneously and use th            em to alter the original dictionary

I'm just really unsure how to construct those for loops...

Link to comment
Share on other sites

Link to post
Share on other sites

Haha believe me, I know. This is an assignment for school and we have to read through that database in this particular function. The database has to be organized like that unfortunately. I did figure it out though (it only took the entire day). I have one question for you though. I have a list of tuples written like this [((name, gender), count)), ((name, gender), count))]. I basically want to take the elements out of each member. So (name, gender) and then count. I can't seem to figure out how to do that though. Any suggestions??

 

Ok, so given a list

 

name_rank_list = [(('freda', 'female'), 2), (('ted', 'male'), 1)]

you can get the "name gender" tuple and rank with this super simple for loop

for name_couple in name_rank_list:   name_gender, rank = name_couple   print "Name and gender tuple:"   print name_gender   print "Rank is {}".format(rank)

EDIT:

If you need the index to update the value, all you have to do is use enumerate:

 

updated_name_rank_list = name_rank_listfor name_couple_id, name_couple in enumerate(name_rank_list):      name_gender, rank = name_couple      rank += 1  #or someother change to the rank   updated_name_rank_list[name_couple_id] = (name_gender, rank)

just remember to never edit the list you're iterating over (this the reason for "update_name_rank_list"), that's bad practice that can result in infinite loops or inconsistancies in your array

Link to comment
Share on other sites

Link to post
Share on other sites

for x in range(len(sub_db)):        for y in range(len(sub_db[x])):            #Here I basically want to take the (name, gender) and count simultaneously and use th            em to alter the original dictionary

I'm just really unsure how to construct those for loops...

 

If I'm understanding the problem, something like what @jszym might do the trick.  You shouldn't need to do a nested loop.

 

If it doesn't, then try something along these lines: since the database you're editing is {(name, gender):{year:(count, rank)}}, and you're updating the (count, rank) tuple for a given year, there's a different way you can iterate over items in your source database/list (the ((name, gender), count) one).

# Database with new valuessource_db = [(('bob', 'm'), 5), (('jane', 'f'), 10)]# Database to updatedest_db = {('bob', 'm'):{1999:(6, 'rank')}, ('jane', 'f'):{1997:(3, 'rank')}for i in source_db:    # Pull out (name, gender) tuple    key = i[0]    # Pull out count value    count_temp = i[1]    # Do whatever comparison for source_db's count and dest_db's count for a year.    # Not necessarily ==, that's just an example/placeholder for whatever comparison you need to do    if count_temp == dest_db[key][year][0]:        new_rank = some code/function to get the new rank        dest_db[key][year] = (count_temp, new_rank)

This approach will iterate over each item in your source_db, look up the corresponding item in dest_db (using the (name, gender) tuple as the lookup key), do some comparison between the count values for both, and then do something to update the rank value (you'll have to fill in the function to update rank).

 

Note that this doesn't account for what the different year values might be.  If every entry in dest_db has the same year, you can hard-code it in and it should work just fine.  If every person has a different year but only has one, you can use the keys() method on the {year:(count, rank)} dictionary to return a list of all the keys, and do thingy.keys()[0] (thingy is the {year:...} dictionary) to get what will be the only value in the list.  Then you can use that to do the index the (count, rank) tuple to update.  But, if everyone has more than one year value, there isn't enough information to update anything as it stands.  You'd need some way to determine a year value for each ((name, gender), count) and use that to update the dest_db entries.

 

jszym also makes a very important point--you do NOT want to do ANYTHING to edit your source_db list while you're iterating over it, or things can break in horrific ways.  If you're going to edit that list, do what jszym does and make a copy of it in a new variable, iterate over the new copy, and update the old one as you go.

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×