I want to check if the 'value' exists in python dictionary and if matches print the 'key'. The problem is, values are in the list.
This script will give the server name based on the provided domain name. It will query the predefined nameserver and gives output accordingly.
I have tried following but it keeps giving me the same output.
if [k for k, v in servers.iteritems() if answer in v]:
print "\nThe domain is in " + v + ".\n"
The script is as follows. Any suggestions other than the original one is welcome.
#!/usr/bin/python
import dns.resolver
import sys
servers = {
'UK':['127.0.0.1'],
'USA':['127.0.0.2','127.0.0.3','127.0.0.4'],
'AUS':['127.0.1.1','127.0.1.2']
}
website = sys.argv[1]
try:
nameserver = dns.resolver.Resolver(configure=False)
nameserver.nameservers = ['198.40.3.6','198.40.3.7']
answer = nameserver.query(website)[0]
answer = str(answer)
if [k for k, v in servers.iteritems() if answer in v]:
print "\nThe domain is in " + v + ".\n"
except Exception as e:
print str(e)
It should give the correct 'key' but it is not. It is giving the same output.
The logic of your if check and the print statement following it are faulty. There's nothing specifically incorrect about how you're finding keys (though you could do it more efficiently), but you're not using that result at all in the rest of your code, so it doesn't really matter.
Try changing your code to this:
matched_keys = [k for k, v in servers.iteritems() if answer in v] # same list comp as before
if matched_keys:
print print "\nThe domain is in " + str(matched_keys) + ".\n" # or maybe use matched_keys[0]?
The way I coded it above will print out the list of all keys that have the answer in them, if there are any. If you're sure there can only be one result, you can use matched_keys[0].
Note that if you expect to be doing this sort of check a lot, with the same set of servers, you should probably change your data structure so that you can do a more efficient check. The current one is O(M*N) where M is the number of checks you need to do and M is the number of values in the dictionary. You could turn that into O(M) by constructing a reversed dictionary:
reversed_servers = {}
for k, v in servers.iteritems():
for address in v:
reversed_servers.setdefault(address, []).append(k) # or reversed_servers[address] = k
You only need to do this setup once. Later you can do any number of efficent lookups with just reversed_servers[answer], with no loop needed.
Note that the code above sets up a dictionary containing lists of all matching keys, if there can be only one for each address (because the values are unique), then you can use the alternative version in the comment, which will map from address to key directly (without a list).
Try this:
result = [k for k in servers.keys() if answer in servers[k]]
if result:
print "\nThe domain is in " + str(servers[result[0]]) + ".\n"
To print the corresponding key, you can use result[0].
Related
I am checking the differences in keys,values from two dictionaries. However I am able to print the differences, but I would like to save the outcome in a variable (are there differences or not, or how many differences are there).
def findDiff(d1, d2, path="", differences = 0):
for k in d1:
if (k not in d2):
print (path, ":")
print (k + " as key not in d2", "\n")
differences += 1
else:
if type(d1[k]) is dict:
if path == "":
path = k
else:
path = path + "->" + k
findDiff(d1[k], d2[k], path, differences)
else:
if d1[k] != d2[k]:
print (path, ":")
print (" - ", k," : ", d1[k])
print (" + ", k," : ", d2[k])
differences += 1
return differences
a = findDiff(moot_params, database_params)
print(a)
This however always results in None if the last dictionary doesn't contain any differences.
Does anybody know how I can return a value using this recursion?
The reason you have to change findDiff(d1[k], d2[k], path, differences) to differences += findDiff(d1[k], d2[k], path) (as I indicated in the comment) is because Python arguments are passed by assignment, and integers are immutable. To make a change in an integer, instead of passing it into the function and changing it inside, you should return how much you're changing it from within inside (as seen in the link's example).
If you don't quite understand the link and integer immutability yet, in simple terms, it means that when you modify differences in findDiff(d1[k], d2[k], path, differences), the differences you already have on the "outside" will not get modified. The solution is to explicitly change differences using +=, giving the recursive functionality you desire.
I have this script that is suppose to rank fruits based on a number.
#! /usr/bin/python
fruits = {'Apple':1,'Banana':2,'Pineapple':3}
alist = [(v, k) for k, v in fruits.items()]
alist.sort(reverse=False)
fruit_order = str(alist).translate(None, "[]()'123456789").replace(", , ", " , ",").replace(" ", "")[1:]
print fruit_order
fruits is actully a list made up with check with .append(fruits)
#! /usr/bin/python
import re
from configobj import ConfigObj
config = ConfigObj('sites.conf')
fruits = []
substance = "juice"
target_list = config['MainConfig']['fruits']
for target in target_list:
if re.search( config[target]['Skiplist'], substance, re.M|re.I):
target = target + "'" + ":" + config[target]['Rank'] + ","
fruits.append(target)
else:
print "Dident pass"
fruits1 = "{'" + "'".join(fruits) + "}"
alist = [(v, k) for k, v in fruits1.list()]
alist.sort(reverse=False)
fruit_rank = str(alist).translate(None, "[]()'123456789").replace(", , ", ",").replace(" ", "")[1:]
print fruit_rank in example 2 prints out a line that looks exactly like test in example 1.
But iam still getting an error on example2, AttributeError: 'str' object has no attribute 'list'
And i can not really figure this one out. How would i do it?
What iam looking for is in the config file i have a rank for each fruit, the line should print out the fruits in its rank.
fruits = {'Apple': 1,'Banana': 2,'Pineapple': 3}
print ','.join(sorted(fruits, key=fruits.get))
You should use the builtin function sorted, and specify that you wish to sort by the ranks instead of by the names themselves. For your first example, here is what I would do. It sorts the dict's keys (the fruit names) by its values (their ranks).
fruits = {'Apple':1,'Banana':2,'Pineapple':3}
sorted_keys = sorted(fruits.keys(), key=lambda k: fruits[k])
Your second example is very hard to read. I would recommend that you comment code that is that complex.
It looks like you are trying to create a string containing Python code, and then execute that code. Like an eval statement. That is not good programming practice. You will want to do something like:
fruits = {} # create dict
for line in my_file.readlines():
fruit_name, rank = function_to_parse_line(line)
fruits[fruit_name] = rank
sorted_keys = sorted(fruits.keys(), key=lambda k: fruits[k])
Now there is a nice separation between the code that reads the data and the code that sorts it. If you wanted to read data from a different kind of file, you can just redefine function_to_parse_line.
I want to be able to transform a dictionary in a list of options that
can be set (with the full path), for example this should pass:
def test_dic_to_args(self):
dic = {"x1": {"x2": "val1"}, "x2": "val3"}
des = ["x1.x2:val1", "x2:val3"]
self.assertEqual(conf.dict_to_args(dic), des)
Now I started to write it and I thought it was easy, but it's more
tricky than I thought, with queues, type checking and so on..
Is there a smart way to solve this problem?
Maybe the best option is still a recursive DFS, what do you think?
If the dictionary is supposed to be arbitrarily nested, a recursive approach is most probably easiest.
def dict_to_args(d, prefix=()):
for k, v in d.iteritems():
if isinstance(v, dict):
for x in dict_to_args(v, prefix + (k,)):
yield x
else:
yield ".".join(prefix + (k,)) + ":" + v
Example:
>>> list(dict_to_args(dic))
['x2:val3', 'x1.x2:val1']
This is how I have been searching for objects in python. Is there any more efficient (faster, simpler) way of doing it?
Obs: A is a known object.
for i in Very_Long_List_Of_Names:
if A == My_Dictionary[i]:
print: "The object you are looking for is ", i
break
The one liner would be: (i for i in List_of_names if A == My_dictionary[i]).next().
This throws a KeyError if there is an item in List_of_names that is not a key in My_dictionary and a StopIteration if the item is not found, else returns the key where it finds A.
I assume you're looking for an object in the values of a Python dictionary.
If you simply want to check for its existence (as in, you don't really care to know which key maps to that value), you can do:
if A in My_Dictionary.values():
print "The object is in the dictionary"
Otherwise, if you do want to get the key associated with that value:
for k, v in My_Dictionary.iteritems():
if v == A:
print "The object you are looking for is ", k
break
EDIT: Note that you can have multiple keys with the same value in the same dictionary. The above code will only find the first occurence. Still, it sure beats having a huge list of names. :-)
Seems to me like you have you're using the dictionary incorrectly if you're searching through all the keys looking for a specific value.
If A is hashable, then store A in a dictionary with its values as i.
d = {A: 'a_name'}
If My_Dictionary is not huge and can trivially fit in memory, and, A is hashable, then, create a duplicate dictionary from it:
d = dict((value, key) for key, value in My_Dictionary.iteritems())
if A in d:
print "word you're looking for is: ", d[A]
Otherwise, you'll have to to iterate over every key:
for word, object_ in My_Dictionary.iteritems():
if object_ == A:
print "word you're looking for is: ", word
I have a dictionary A, and a possible entry foo. I know that A[foo] should be equal to x, but I don't know if A[foo] has been already defined. In any case if A[foo] has been defined it means that it already has the correct value.
It is faster to execute:
if foo not in A.keys():
A[foo]=x
or simply update
A[foo]=x
because by the time the computer has found the foo entry, it can as well update it. While if not I would have to call the hash table two times?
Thanks.
Just add items to the dictionary without checking for their existence. I added 100,000 items to a dictionary using 3 different methods and timed it with the timeit module.
if k not in d: d[k] = v
d.setdefault(k, v)
d[k] = v
Option 3 was the fastest, but not by much.
[ Actually, I also tried if k not in d.keys(): d[k] = v, but that was slower by a factor of 300 (each iteration built a list of keys and performed a linear search). It made my tests so slow that I left it out here. ]
Here's my code:
import timeit
setup = """
import random
random.seed(0)
item_count = 100000
# divide key range by 5 to ensure lots of duplicates
items = [(random.randint(0, item_count/5), 0) for i in xrange(item_count)]
"""
in_dict = """
d = {}
for k, v in items:
if k not in d:
d[k] = v
"""
set_default = """
d = {}
for k, v in items:
d.setdefault(k, v)
"""
straight_add = """
d = {}
for k, v in items:
d[k] = v
"""
print 'in_dict ', timeit.Timer(in_dict, setup).timeit(1000)
print 'set_default ', timeit.Timer(set_default, setup).timeit(1000)
print 'straight_add ', timeit.Timer(straight_add, setup).timeit(1000)
And the results:
in_dict 13.090878085
set_default 21.1309413091
straight_add 11.4781760635
Note: This is all pretty pointless. We get many questions daily about what's the fastest way to do x or y in Python. In most cases, it is clear that the question was being asked before any performance issues were encountered. My advice? Focus on writing the clearest program you can write and if it's too slow, profile it and optimize where needed. In my experience, I almost never get to to profile and optimize step. From the description of the problem, it seems as if dictionary storage will not be the major bottle-neck in your program.
Using the built-in update() function is even faster. I tweaked Steven Rumbalski's example above a bit and it shows how update() is the fastest. There are at least two ways to use it (with a list of tuples or with another dictionary). The former (shown below as update_method1) is the fastest. Note that I also changed a couple of other things about Steven Rumbalski's example. My dictionaries will each have exactly 100,000 keys but the new values have a 10% chance of not needing to be updated. This chance of redundancy will depend on the nature of the data that you're updating your dictionary with. In all cases on my machine, my update_method1 was the fastest.
import timeit
setup = """
import random
random.seed(0)
item_count = 100000
existing_dict = dict([(str(i), random.randint(1, 10)) for i in xrange(item_count)])
items = [(str(i), random.randint(1, 10)) for i in xrange(item_count)]
items_dict = dict(items)
"""
in_dict = """
for k, v in items:
if k not in existing_dict:
existing_dict[k] = v
"""
set_default = """
for k, v in items:
existing_dict.setdefault(k, v)
"""
straight_add = """
for k, v in items:
existing_dict[k] = v
"""
update_method1 = """
existing_dict.update(items)
"""
update_method2 = """
existing_dict.update(items_dict)
"""
print 'in_dict ', timeit.Timer(in_dict, setup).timeit(1000)
print 'set_default ', timeit.Timer(set_default, setup).timeit(1000)
print 'straight_add ', timeit.Timer(straight_add, setup).timeit(1000)
print 'update_method1 ', timeit.Timer(update_method1, setup).timeit(1000)
print 'update_method2 ', timeit.Timer(update_method2, setup).timeit(1000)
This code resulted in the following results:
in_dict 10.6597309113
set_default 19.3389420509
straight_add 11.5891621113
update_method1 7.52693581581
update_method2 9.10132408142
if foo not in A.keys():
A[foo] = x
is very slow, because A.keys() creates a list, which has to be parsed in O(N).
if foo not in A:
A[foo] = x
is faster, because it takes O(1) to check, whether foo exists in A.
A[foo] = x
is even better, because you already have the object x and you just add (if it already does not exist) a pointer to it to A.
There are certainly faster ways than your first example. But I suspect the straight update will be faster than any test.
foo not in A.keys()
will, in Python 2, create a new list with the keys and then perform linear search on it. This is guaranteed to be slower (although I mainly object to it because there are alternatives that are faster and more elegant/idiomatic).
A[foo] = x
and
if foo not in A:
A[foo] = x
are different if A[foo] already exists but is not x. But since your "know" A[foo] will be x, it doesn't matter semantically. Anyway, both will be fine performance-wise (hard to tell without benchmarking, although intuitively I'd say the if takes much more time than copying a pointer).
So the answer is clear anyway: Choose the one that is much shorter code-wise and just as clear (the first one).
If you "know" that A[foo] "should be" equal to x, then I would just do:
assert(A[foo]==x)
which will tell you if your assumption is wrong!
A.setdefault(foo, x) but i'm not sure it is faster then if not A.has_key(foo): A[foo] = x. Should be tested.