Python: Can a dictionary have both tuples and strings as key ? - python-2.7

Can I have a single dictionary, in which some of the keys are tuples and other are strings, at the same time ?

The only two requirements for dictionary keys in python is that they must be unique (ie - you can't use the same key twice in a single dictionary) and each key must be hashable (ie - it must have a unique id for comparison). Ints, floats, strings, dictionaries, tuples, .. etc are all hashable.
Example of using a tuple and a string as keys:
>>> mydict = {('you', 'can'):'do', 'this':('if', 'you', 'want')}
>>> print(mydict)
{'this': ('if', 'you', 'want'), ('you', 'can'): 'do'}
>>> mydict[('you', 'can')]
'do'
>>> mydict['this']
('if', 'you', 'want')
Example showing tuples and strings have a hash method :
>>> ('you', 'can').__hash__()
-5095345937749811518
>>> 'this'.__hash__()
2314053222244391272

Related

List to Dictionary with key to be a String Counter

I am new to python and was trying to implement a dictionary from a list with the key value to be a string counter
ex. the list is ['a','b','c']
I want this list to be displayed as
dict {'A1':'a','A2':'b','A3':'c'}
Thanks in advance
Given I understand your question correctly you want for the i-th element, a key-value pair 'Ai':c with c the character at position i. You can use dictionary comprehension:
{'A%s'%i:e for i,e in enumerate(data,1)}
Running this in the interpreter:
>>> data = ['a','b','c']
>>> {'A%s'%i:e for i,e in enumerate(data,1)}
{'A2': 'b', 'A3': 'c', 'A1': 'a'}
This is dictionary comprehension. Dictionary comprehension has as syntax:
{key(element):value(element) for element in iterable}
Where key and value are expressions that do something with element. For each element in the iterable. It will evaluate the expression and associate the value with the derived key.

Naming dictionaries arbitrarily

I have list=[gender,employment type] and i wanted to create a dictionary named gender and another dictionary named employment type. Can i name my dictionaries something as follows:
> list[0] = {key1: value}
> list[1] = {key2: value}
I wanted to name my dictionary arbitrarily depending on certain input.Is it possible to declare a dictionary using a string value from a list?
You may want to look into a combination of map and enumerate. I've linked to the 2.x docs because of your tag, but I believe the functions are almost identical in 3.x.
Using a map:
>>> list=["gender", "employment type"]
>>> mapped=map(lambda x: {"key":x})
[{'key': 'gender'}, {'key': 'employment type'}]
with enumerate:
>>> list=["gender", "employment type"]
>>> map(lambda (i, x): {"key"+str(i):x}, enumerate(list))
[{'key0': 'gender'}, {'key1': 'employment type'}]
Given more deeply-nested structures — something like list=[[gender], [employment type]] — you can define a more intricate function as your mapper.
Alternatively, if you are looking at an array of [gender, employment type] tuples (something that more closely resembles [(gender, employment type)]) — you may want to look into "unzipping" the data. See the SO question: A Transpose/Unzip Function in Python (inverse of zip).

Add values from a list of dictionaries to separate lists and find/count common values

I have a list containing dictionaries like this:
[{"abc":"da123-tap","efg":"xyzf","acd":"123-brf"}, {"abc":"ab234-tap","efg":"yuvi","acd":"345-brf"}]
I want all the values of abc in a list (list1) and all the values of efg in another list (list2).
Update to question:
I read a file to get this list of dictionaries:
[{"Sample":"da123-tap","Name":"john","dof":"Date(304239600000)","Account":"Clinic1"},
{"Sample":"da456-tap-tap","Name":"smith","dof":"Date(304239600000)","Account":"Clinic2"},
{"Sample":"da678-tap-tap","Name":"jane","dof":"Date(304239600000)","Account":"Clinic1"},
{"Sample":"da987-tap-tap","Name":"doe","dof":"Date(304239600000)","Account":"Clinic2"}]
Find:
Values from Sample in list1
Values from Account in list2
Count values of Sample that belong to Clinic1
Count values of Sample that belong to Clinic2
Only for educational reasons, the elegant way to direct values of different keys into multiple lists could be to use zip() and unpacking:
>>> l = [
... {"abc":"da123-tap","efg":"xyzf","acd":"123-brf"},
... {"abc":"ab234-tap","efg":"yuvi","acd":"345-brf"}
... ]
>>>
>>> a, b = zip(*[(item["abc"], item["efg"]) for item in l])
>>> print(a)
('da123-tap', 'ab234-tap')
>>> print(b)
('xyzf', 'yuvi')

Intersection of a set and list of dictionaries

I have a set my_set = ("a","b","c","d","z") and a list my_list=[{"a",0.5},{"c",0.6},{"b",0.9},{"z",0.5},{"m",0.0}]. I would like to have a list with items containing keys in my_set only. In this case the result I would like to have is new_list=[{"a",0.5},{"c",0.6},{"b",0.9},{"z",0.5}]
The list and set is large. Is there an efficient way to accomplish this?
Assuming that that's actually a set and a list of dicts, as stated in the question, you can try this:
In [1]: my_set = set(["a","b","c","d","z"])
In [2]: my_list=[{"a":0.5},{"c":0.6},{"b":0.9},{"z":0.5},{"m":0.0}]
In [3]: [d for d in my_list if all(k in my_set for k in d)]
Out[3]: [{'a': 0.5}, {'c': 0.6}, {'b': 0.9}, {'z': 0.5}]
This simply uses a list comprehension to check that all the keys in the dicts are contained in the set. This will have complexity of O(nm), for n dicts in the list, with m keys each (m being 1 in your case) and assuming that set-lookup is always O(1).
Note, however, that you do not really need a list of dictionaries, since all the keys seem to be different (in this example, at least), so a single dictionary would be enough.

Operate on list containing dictionary and return dictionary

I have a list of elements where each element is a type of dictionary. I want this implementation to be done in Python.
My input is like this:
MyList = [{'Kathy':1, 'Bob':1, 'Spencer':1}, {'Kathy':4, 'Cynthia':2, 'Bob':3, 'Goldman':1}, {'Spencer':2, 'Bob':1}]
My output should be like this:
MyDict = {'Kathy':5, 'Bob':5, 'Spencer':3, 'Cynthia':2, 'Goldman':1}
Use a Counter:
>>> from collections import Counter
>>> myList = [{'Kathy':1, 'Bob':1, 'Spencer':1}, {'Kathy':4, 'Cynthia':2, 'Bob':3, 'Goldman':1}, {'Spencer':2, 'Bob':1}]
>>> myDict = Counter()
>>> for d in myList:
myDict.update(d)
>>> myDict
Counter({'Kathy': 5, 'Bob': 5, 'Spencer': 3, 'Cynthia': 2, 'Goldman': 1})
Here's one way to do it using defaultdict.
import collections
MyDict = collections.defaultdict(int)
for d in MyList:
for k,v in d.items():
MyDict[k] += v
MyDict = dict(MyDict) #if you want a normal dict
Edit: Looks like the Counter version is nicer. But it's still important to know about defaultdicts in case you ever have to do something other than adding ints. They're useful for accumulating lists or sets for instance.
Here is another way of doing this, what seems to me a little more pythonic than the alternatives offered so far (but it will more likely use more memory, since it is not based on a generator):
my_dict = {key: 0
for one_dict in list_of_dicts
for key in one_dict.keys()}
my_dict = {key: one_dict[key]+my_dict[key]
for one_dict in list_of_dicts
for key in one_dict.keys()}
Edit: Thanks #ShadowRanger by the insight, however, in this case I would rather use the .keys() option to recover the key specifically, and not simply iterate over every key-pair in the dict, because the key will be needed to add such key to the final dictionaries.