views:

133

answers:

4

I am trying to create a small server type application and have a question regarding organizing data with dicts. Right now I am grouping the data using the connection socket (mainly to verify where it's coming from and for sending data back out). Something like this: connected[socket] = account_data. Basically, each connected person will have account data. Since certain fields will be used a lot for comparing and checking information, such as an account ID, I want to speed things up with another dict.

For example: to find an accountID with the above method, I would have to use a for loop to go through all available connections in connected, look at the accountID in account_data for each, and then compare it. This seems to be a slow way to do it. If I could create a dict and use the accountID as the key, I think it could speed things up a little. The problem is, I plan on using 3 different dicts all ordered differently. Some data may change frequently and it seems more of a hassle to update every single dict once information changes; is there anyway to link them together?

Maybe an easier way of trying to explain what I am asking is: You have Dict A, Dict B, Dict C, and Data. Dict A, B, and C all contain the same Data. I want it so if something changes in Data, the Data in Dict A, B, and C all change. I can of course always do dict A = data, dict B = data, etc but would get repetitive in the code after awhile. I know the data is set once the dict is created so I'm not really sure if there is a solution to this. I am just looking for advice on the best way to organize data in this situation.

A: 

Maybe one of the publish/subscribe modules for Python can help you here? See this question.

Eli Bendersky
A: 

If you have references to dictionaries, an update to the dictionary will be reflected to everything with a reference.

A customer connects and retains a socket, sock. You load his account and stick it in connections[sock]. Then you keep a dictionary of account IDs (the other way) with references to the accounts, accounts[account_id]. Let's try that...

connected = {}
accounts = {}

def load_account(acct):
    return db_magic(acct)                             # Grab a dictionary from the DB

def somebody_connected(sck, acct):
    global connected, accounts
    account = load_account(acct)
    connected[sck] = account                          # Now we have it by socket
    accounts[acct["accountid"]] = account             # Now we have it by account ID

Since we assigned account to two different places, any change to that dictionary (in either structure) will be reflected in the other. So...

def update_username(acct_id, new_username):
    accounts[acct_id]["username"] = new_username

def what_is_my_username(sck):
    sck.send(connected[sck]["username"])              # In response to GIMME_USERNAME

The change we execute in update_username will automatically be picked up when we do the sck.send, because the reference is exactly the same.

Jed Smith
Thanks to everyone's response. Definitely makes sense to use modules and classes to accomplish what I need. Will give it a try.
Chuck
+2  A: 

First off, the data, needn't be be replicated. You can well have 3 dictionaries each using a different key, but having the same reference as its value.

Doing so you only need to change the value object once and this will be reflected in all dictionaries (or more precisely since the the dictionaries only store a reference, they'll be up to date).

Next you need to ensure "referencial integrity" i.e. if a particular record is deleted, corresponding dictionary entry needs to be be deleted in all 3 dictionaries, and, if the record gets modified, the dictionaries with a key that is now changed also need to be have the record removed and re-added under the new key. This can be done with a class that holds all 3 dictionaries and has Add(), Remove() and (if applicable) Update() methods.

mjv
+1  A: 

Just do something like:

connected[socket] = accountids[account_data.accountid] = account_data

assuming account_data is a mutable object with attributes, this will reference that same object as a value in both dicts, with different keys of course. It doesn't have to be on one statement, i.e.:

connected[socket] = account_data
accountids[account_data.accountid] = account_data

the multiple assignments in the same statement are just a convenience; what makes it work the way you want is that Python universally operates by "object reference" (in assignments, argument passing, return statements, and so on).

Alex Martelli