Dive Into Python Output Error - python

I'm running this code from Dive Into Python:
def buildConnectionString(params):
"""Build a connection string from a dictionary of parameters.
Returns string."""
return ";".join(["%s=%s" % (k, v) for k, v in params.items()])
if __name__ == "__main__":
myParams = {"server":"mpilgrim", \
"database":"master", \
"uid":"sa", \
"pwd":"secret" \
}
print buildConnectionString(myParams)
The book says its output should be:
server=mpilgrim;uid=sa;database=master;pwd=secret
But when I run it it comes out in reverse:
pwd=secret;database=master;uid=sa;server=mpilgrim
Any ideas why?

The fact that it is in exactly reverse order is really just a coincidence. Run the code with a different version/implementation of python and you'll likely get a different ordering. The reason for this is because in python dictionaries are not ordered so the order of the ouput of your function is not well defined. (The order that you put things into the dictionary is not the order that they are yielded as you iterate over the dictionary).
If you want a specific order, you can sort parames.items() using the builtin sorted function (optionally using the key keyword to tell sorted how to sort the items). Another option is to use an OrderedDict from the collections module which appeared in python2.7 (as pointed out by sr2222).

Because you are printing a dictionary, and dictionaries are unordered. The order a dictionary is iterated through is dependent on a number of factors including interpreter type, interpreter version, and OS. If you want it to come out the same order you put it in, you have to use collections.OrderedDict instead. Alternatively, as mgilson said in his answer, you could sort the dictionary contents before printing it, but given that the order you want is not alphabetical, it's probably more trouble than it is worth.

Related

confused about dictionary in python

I have the following dict
commands = {
'cmd1':"configure terminal",
'cmd2':"router",
'cmd3':"MPLS"
}
when I execute the following code:
`for cmd in commands:
print(cmd)
I always get cmd3 as 1st print, why is that?
I am doing something wrong.
Python dictionaries are unordered. Things will come out of them in some order when you iterate over them, but the order probably will not be the same order in which you added them. This is by design.
You can use collections.orderedDict if you need order. Or, in this case, since the keys are not actually needed, just use a list.
To see what the values are - use sorted on the resulting list of items:
for key,value in sorted(commands.items()):
print(key)
print(value)
print commands[key] # same as line above

Python Dictionary with Variable Array keys

self.PARSE_TABLE={"$_ERROR":self.WEEK_ERRORS,"$_INFORM":self.WEEK_INFORM,"$_REDIR":self.WEEK_REDIRECTS,"$_SERVER_ERROR":self.WEEK_SERVER_ERROR,"$_BYTES":self.WEEK_BYTES,"$_HITS":self.WEEK_HITS}
for j in self.PARSE_TABLE:
print j
break
When I run this on my python the first element I get is S_REDIR can someone explain why?
Dictionaries don't maintain order. The order you get from iterating over them may not be the order in which you inserted the elements. This is the price you pay for near-instant lookup of values by key. In short, the behavior you are seeing is correct and expected, and may even vary from run to run of the Python interpreter.
It normal behaviour. Inside dictionary and set using hash codes. If you want orderd keys use self.PARSE_TABLE.keys.sort(). Also you can use OrderedDict from collection library.
Dictionary by default stores all the keys in its own convenient order rather to the order we gave.
If the order of the keys should be maintained, you can use OrderedDict which came to implementation from the python version 3.0
P.S. I don't think sorting keys would do any help in preserving the order given.

Look up python dict value by expression

I have a dict that has unix epoch timestamps for keys, like so:
lookup_dict = {
1357899: {} #some dict of data
1357910: {} #some other dict of data
}
Except, you know, millions and millions and millions of entries. I'd like to subset this dict, over and over again. Ideally, I'd love to be able to write something like I can in R, like:
lookup_value = 1357900
dict_subset = lookup_dict[key >= lookup_value]
# dict_subset now contains {1357910: {}}
But I confess, I can't find any actual proof that this is something Python can do without having, one way or the other, to iterate over every row. If I understand Python correctly (and I might not), key lookup of the form key in dict uses binary search, and is thus very fast; any way to do a binary search, on dict keys?
To do this without iterating, you're going to need the keys in sorted order. Then you just need to do a binary search for the first one >= lookup_value, instead of checking each one for >= lookup_value.
If you're willing to use a third-party library, there are plenty out there. The first two that spring to mind are bintrees (which uses a red-black tree, like C++, Java, etc.) and blist (which uses a B+Tree). For example, with bintrees, it's as simple as this:
dict_subset = lookup_dict[lookup_value:]
And this will be as efficient as you'd hope—basically, it adds a single O(log N) search on top of whatever the cost of using that subset. (Of course usually what you want to do with that subset is iterate the whole thing, which ends up being O(N) anyway… but maybe you're doing something different, or maybe the subset is only 10 keys out of 1000000.)
Of course there is a tradeoff. Random access to a tree-based mapping is O(log N) instead of "usually O(1)". Also, your keys obviously need to be fully ordered, instead of hashable (and that's a lot harder to detect automatically and raise nice error messages on).
If you want to build this yourself, you can. You don't even necessarily need a tree; just a sorted list of keys alongside a dict. You can maintain the list with the bisect module in the stdlib, as JonClements suggested. You may want to wrap up bisect to make a sorted list object—or, better, get one of the recipes on ActiveState or PyPI to do it for you. You can then wrap the sorted list and the dict together into a single object, so you don't accidentally update one without updating the other. And then you can extend the interface to be as nice as bintrees, if you want.
Using the following code will work out
some_time_to_filter_for = # blah unix time
# Create a new sub-dictionary
sub_dict = {key: val for key, val in lookup_dict.items()
if key >= some_time_to_filter_for}
Basically we just iterate through all the keys in your dictionary and given a time to filter out for we take all the keys that are greater than or equal to that value and place them into our new dictionary

python dictionary sorting oddly (want non-alphabetical)

so I am trying to send a packet with some keys that i have put into a dictionary. these need to be printed in a specific order, so I've tried to make a function to reorder them. I assume python is doing something to rearrange in the order I don't want, but i'm not sure why.
I'm currently using this function to try and achieve this.
def array_sort(array, sort): #yeah, it's array cuz i php like that.
ordered = {}
for i in range(0,len(sort)):
if sort[i] in array:
ordered[sort[i]] = array[sort[i]]
keys = array.keys()
return ordered
order = "l5,l4,l3,l2,q,y,k,k3,d1,z,p,c,b,d3,dt,N,n,a,h,v".split(',')
keys = array_sort(infos, order)
for some reason this isn't working, infos is the list of keys in alphabetical order, i'm just not sure why the function is outputting the keys in an odd order. (a first, when 15 should be first :S)
If you know a better way to do this feel free to tell me, I just recently started on python, so I'm not that familiar.
EDIT:
I was able to print the keys in the correct order using this immediately after making the order dictionary. even if it was just output as a string the order would be preserved (for the time being) and you could .split() it again to get the dictionary in the correct order (i think).
for i in range(0, len(order)):
if order[i] in infos:
packet += order[i] + '="' + infos[order[i]] + '" '
Since dictionaries in Python are unordered and all that you need is to output results ordered by the specified rule you can do something like this:
order = "l5,l4,l3,l2,q,y,k,k3,d1,z,p,c,b,d3,dt,N,n,a,h,v".split(',')
for key in order:
print key, infos.get(key)#if infos is your dictionary
Or you can get/pass list instead of dict the following way:
print [(key, infos.get(key)) for key in order]
Python dictionaries are not ordered containers. Take a look at the collections.OrderedDict instead
Python dictionaries order their keys based on its hash, which will make it seem random. I recommend using OrderedDict to get your keys in order.

Python equiv. of PHP foreach []?

I am fetching rows from the database and wish to populate a multi-dimensional dictionary.
The php version would be roughly this:
foreach($query as $rows):
$values[$rows->id][] = $rows->name;
endforeach;
return $values;
I can't seem to find out the following issues:
What is the python way to add keys to a dictionary using an automatically numbering e.g. $values[]
How do I populate a Python dictionary using variables; using, for example, values[id] = name, will not add keys, but override existing.
I totally have no idea how to achieve this, as I am a Python beginner (programming in general, actually).
values = collections.defaultdict(list)
for rows in query:
values[rows.id].append(rows.name)
return values
Just a general note:
Python's dictionaries are mappings without order, while adding numerical keys would allow "sequential" access, in case of iteration there's no guarantee that order will coincide with the natural order of keys.
It's better not to translate from PHP to Python (or any other language), but rather right code idiomatic to that particular language. Have a look at the many open-source code that does the same/similar things, you might even find a useful module (library).
all_rows=[]
for row in query:
all_rows.append(row['col'])
print(all_rows)
You can do:
from collections import defaultdict
values = defaultdict(list)
for row in query:
values[row.id].append(row.name)
return values
Edit: forgot to return the values.

Categories