I'm in pretty far over my head right now for Python scripting and don't really understand what I'm doing.
I have a dictionary where the keys are strings and the values are lists of strings. I need to sort the strings within the list alphanumerically such that
"role_powerdns": [
"name-2.example.com",
"name-1.example.com",
"name-3.example.com"
],
Looks like this
"role_powerdns": [
"name-1.example.com",
"name-2.example.com",
"name-3.example.com"
],
The full original code I'm working off of is here for reference. https://github.com/AutomationWithAnsible/ansible-dynamic-inventory-chef/blob/master/chef_inventory.py
I don't fully understand myself how the code I'm working off of works, I just know the data structure it's returning.
My local additions to that base code is filtering out IPs and inserting .sub into the strings. I've tried reusing the comprehension syntax I've got below for modifying the strings to sort the strings. Could someone show provide an example of how to iterate through a nested structure like this? Alternatively if doing this sort of sorting so late in the script is not appropriate, when generally should it be handled?
def filterIP(fullList):
regexIP = re.compile(r'\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}$')
return filter(lambda i: not regexIP.search(i), fullList)
groups = {key : [domain.replace('sub.example.com', 'example.com') for domain in filterIP(list(set(items)))] for (key, items) in groups.iteritems() }
print(self.json_format_dict(groups, pretty=True))
If d is your dictionary, you can sort all its values by
for _, l in d.items():
l.sort()
fuglede's answer almost worked for me. What I needed to do instead was use iteritems. items was doing some funky local version that was being thrown away after the code block was done with it per this
Iterating over dictionaries using 'for' loops
for key, value in groups.iteritems():
value.sort()
Related
Rookie here and I couldn't find a proper explanation for this.
We have a simple dict:
a_dict = {'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
to loop through and access the values of this dict I have to call
for key in a_dict:
print(key, '->', a_dict[key])
I am saying about
a_dict[key]
specifically. Why python use this convention? Where is a logic behind this? When I want to get values of a dictionary I should call it something like
a_dict[value] or a_dict[values] etc
instead (thinking logically).
Could anyone explain it to make more sense please?
edit:
to be clear: why python use a_dict[key] to access dict VALUE instead of a_dict[value]. LOGICALLY.
according to your question, I think you meant why python does not use index instead of key to reach values in the dict.
Please take note that there are 4 main data container in python, and each for its usage. (there are also other containers like counter and ...)
for example elements of list and tuple is reachable by their indices.
a = [1,2,3,4,5]
print(a[0]) would print 1
but dictionary as its name shows, maps from some objects (keys in python terminology) to some other objects(values in python terminology). so we would call the key instead of index and the output would be the value.
a = { 'a':1 , 'b':2 }
print(a['a']) would print 1
I hope it makes it a bit more clear for you.
I think you are misunderstanding some terminology around dictionaries:
In your example, your keys are color, fruit, and pet.
Your values are blue, apple, and dog.
In python, you access your values by calling a_dict[key], for example a_dict["color"] will return "blue".
If python instead used your suggested method of a_dict[value], you would have to know what your value was before trying to access it, e.g. a_dict["blue"] would be needed to get "blue", which makes very little sense.
As in Feras's answer, try reading up more on how dictionaries work here
Its because, a dictionary in python, maps the keys and values with a hash function internally in the memory.
Thus, to get the value, you've to pass in the key.
You can sort of think it like indices of the list vs the elements of the list, now to extract a particular element, you would use lst[index]; this is the same way dictionaries work; instead of passing in index you would've to pass in
the key you used in the dictionary, like dict[key].
One more comparison is the dictionary (the one with words and meanings), in that the meanings are mapped to the words, now you would of course search for the word and not the meaning given to the word, directly.
You are searching for a value wich you don't know if it exists or not in the dict, so the a_dict[key] is logic and correct
I have values in a list of lists.
I would like to send the whole block to a conversion function which then returns all the converted values in the same structure.
my_list = [sensor1...sensor4] = [hum1...hum3] = [value1, value2, value3, value4]
So several nested lists
def conversion(my_list): dictionaries
for sensor in my_list:
for hum in sensor:
for value in hum:
map(function, value)
Is there a way to do a list comprehension as a one liner? I'm not sure how to use the map function in comprehensions especially when you have several nested iterations.
map(function, value)
Since you are just mapping a function on each value, without collecting the return value in a list, using a list comprehension is not a good idea. You could do it, but you would be collecting list items that have no value, for the sole purpose of throwing them away later—just so you can save a few lines that actually serve a much better purpose: Clearly telling what’s going on, without being in a single, long, and complicated line.
So my advice would be to keep it as it is. It makes more sense like that and clearly shows what’s going on.
I am however collecting the values. They all need to be converted and saved in the same structure as they were.
In that case, you still don’t want a list comprehension as that would mean that you created a new list (for no real reason). Instead, just update the most-inner list. To do that, you need to change the way you’re iterating though:
for sensor in my_list:
for hum in sensor:
for i, value in enumerate(hum):
hum[i] = map(function, value)
This will update the inner list.
Alternatively, since value is actually a list of values, you can also replace the value list’s contents using the slicing syntax:
for sensor in my_list:
for hum in sensor:
for value in hum:
value[:] = map(function, value)
Also one final note: If you are using Python 3, remember that map returns a generator, so you need to convert it to a list first using list(map(function, value)); or use a list comprehension for that part with [function(v) for v in value].
This is the right way to do it. You can use list comprehension to do that, but you shouldn't for code readability and because it's probably not faster.
Python v3.4.2
I've created a dictionary from a list of keys and stored the number of times the key occurs.
My code works as intended, but I'm unsure WHY it works:
count_dict = {key: key_list.count(key) for key in key_list}
I see that for every key in key_list, I'm adding 'key' and 'count' value pairs to the dictionary. But why does this syntax work? I would expect to need to declare an empty dictionary and then add the key value pairs within a for..in.. loop.
It appears to work for lists as well. But when I try something such as:
print(x) for x in key_list
I get a syntax error.
this is known as a dictionary comprehension
it was introduced in python 2.7
see: https://docs.python.org/2/tutorial/datastructures.html#dictionaries
there are also set comprehensions, list comprehensions, generator statements...
however you are right you cannot just write arbitrary code and expect it to work
ie print(x) for x in key_list is indeed a syntax error
This is a question and answer I wanted to share, since I found it very useful.
Suppose I have a dictionary accessible with different keys. And at each position of the dictionary I have a list of a fixed length:
a={}
a["hello"]=[2,3,4]
a["bye"]=[0,10,100]
a["goodbye"]=[2,5,50]
I was interested to compute the sum across all entries in a using only position 1 of their respective lists.
In the example, I wanted to sum:
finalsum=sum([3,10,5]) #-----> 18
Just skip the keys entirely, since they don't really matter.
sum(i[1] for i in a.itervalues())
Also as a side note, you don't need to do a.keys() when iterating over a dict, you can just say for key in a and it will use the keys.
You can use a.values() to get a list of all the values in a dict. As far as I can tell, the keys are irrelevant. a.itervalues() works by iterating rather than constructing a new list. By using this, and a generator expression as the argument to sum, there are no extraneous lists created.
I used list-comprehensions for my one line solution(here separated in two lines):
elements=[a[pos][1] for pos in a.keys()] #----> [3,5,10]
finalsum=sum(elements)
I'm happy with this solution :) , but, any other suggestions?
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.