Convert this list from stdin into dictionary - python

I am new to Python and need help with converting a list "lis" into a dictionary "dic". The list is generated by reading lines from stdin as follows-
lis = sys.stdin.readlines()
['San Jose\t200.82\n', 'California\t115.15\n', 'San Jose\t20.20\n', 'Texas\t300.10\n', 'San Jose\t100.50\n']
I have done the following to convert an item in list into key,value but dont know how to store this in a dictionary.
for item in lis:
k,v1 = item.split('\t')
v = float(v1)
print k,v
I would like to store this in a dictionary as follows
{'San Jose':200.82, 'California':115.15 .....etc}
Could you please show me how to do this efficiently? Later on I would like to load this dictionary into Pandas DataFrame.

You're almost there:
dic = {}
for item in lis:
k,v1 = item.split('\t')
v = float(v1)
print k,v
dic[k] = v
Of course, you could simplify this with a comprehension:
dic = {item.split('\t')[0]:float(item.split('\t')[1]) for item in lis}
It seems that you want multiple values associated with each key. For that, use a defaultdict:
from collections import defaultdict
dic = defaultdict(list)
for item in lis:
k,v1 = item.split('\t')
v = float(v1)
print k,v
dic[k].append(v)
Of course, you could just do the heavy-lifting yourself:
dic = {}
for item in lis:
k,v1 = item.split('\t')
v = float(v1)
print k,v
if k not in dic:
dic[k] = []
dic[k].append(v)

This should work -
dic = {}
for k,v in [e.strip().split("\t") for e in lis]:
dic[k] = v
#{'San Jose': '100.50', 'California': '115.15', 'Texas': '300.10'}
Or more succinctly -
dic = {k:v for k,v in [e.strip().split("\t") for e in lis]}
If you don't want to overwrite previous values -
dic = {}
for k,v in [e.strip().split("\t") for e in lis]:
if k not in dic:
dic[k] = v
If you want to have multiple values for the same key.
dic = {}
for k,v in [e.strip().split("\t") for e in lis]:
if k not in dic:
dic[k] = [v]
else:
dic[k].append(v)
'''
Output of the Dictionary.
{
'San Jose': ['200.82', '20.20', '100.50'],
'California': ['115.15'],
'Texas': ['300.10']
}
'''

Related

Is there a better way of re-arranging dictionary values?

I have the following dictionary:
files = {
'Input.txt': 'Randy',
'Code.py': 'Stan',
'Output.txt': 'Randy'}
I would like to return a dictionary where the keys are the names and where the corresponding value is a list of the filename:
{'Randy': ['Input.txt', 'output.txt'], 'Stan': ['Code.py']}
I managed to do it with 2 for loops:
def group_by_owners(files):
my_dict = {}
for value in files.values():
if value not in my_dict:
my_dict[value] = []
for key, value in files.items():
if value in my_dict.keys():
my_dict[value].append(key)
return my_dict
Is there a more efficient / elegant way of doing this?
Thanks
Option 1: defaultdict
Default dictionary with a default value of an empty list, so you append values to it.
This solution is preferable.
files = {
'Input.txt': 'Randy',
'Code.py': 'Stan',
'Output.txt': 'Randy'}
from collections import defaultdict
inv_map = defaultdict(list)
{inv_map[v].append(k) for k, v in files.items()}
# {'Randy': ['Input.txt', 'Output.txt'], 'Stan': ['Code.py']}
print(inv_map)
Option 2: Dictionary
files = {
'Input.txt': 'Randy',
'Code.py': 'Stan',
'Output.txt': 'Randy'}
inv_map = {}
for k, v in files.items():
inv_map[v] = inv_map.get(v, []) + [k]
# {'Randy': ['Input.txt', 'Output.txt'], 'Stan': ['Code.py']}
print(inv_map)
Here is my take on this. Using defaultdict to avoid creating the initial list, and just use append
from collections import defaultdict
def group_by_owners(files):
# Creates a dictionary that it's initial value is a list
# therefore you can just start using `append`
result = defaultdict(list)
for key, value in files.items():
result[value].append(key)
return result

Concatenate values in python dictionary

I have a python dictionary and I'd like to concatenate the values of value[0] and a list in value [1]
so
dict={ 'Key1':['MASTER',['_A','_B','_C']]}
and expected output is of calling Key1 is
[['MASTER_A','MASTER_B','MASTER_C']]
Use a nested comprehension:
d = {'Key1':['MASTER',['_A','_B','_C']]}
result_dict = {k: [v[0] + l for l in v[1]] for k,v in d.items()}
For example:
>>> result_dict = {k: [v[0] + l for l in v[1]] for k,v in d.items()}
>>> result_dict
{'Key1': ['MASTER_A', 'MASTER_B', 'MASTER_C']}
Try this :
d = {'Key1':['MASTER',['_A','_B','_C']]}
out = [d['Key1'][0]+i for i in d['Key1'][1]]
Output :
['MASTER_A', 'MASTER_B', 'MASTER_C']
To assign it to the key, do :
d['Key1'] = out

How do I create a dictionary from two lists in python while maintaining all key value information?

Example:
last_names = ['Bakir','Jose','Jose','Pierce']
university = ['Davis', 'Stanford', 'George Town', 'Berkeley']
Desire the Following
resulting_dictionary = {'Bakir':'Davis', 'Jose': ['Stanford', 'George Town'], 'Pierce':'Berkeley'}
I've tried the following
dictionary = {key:value for key, value in zip(last_names, university)}
But obtained the following:
{'Bakir': 'Davis', 'Jose': 'George Town', 'Pierce': 'Berkeley'}
Due to duplicate key value in last name list.
Thoughts?
Use defaultdict
from collections import defaultdict
d = defaultdict(list)
for k, v in zip(last_names, university):
d[k].append(v)
You can use the dict.setdefault method to initialize new keys with sub-lists:
dictionary = {}
for k, v in zip(last_names, university):
dictionary.setdefault(k, []).append(v)
You need to set the value to a list, and check whether the key already exists and append to it.
dictionary = {}
for key, value in zip(last_names, university):
if key in dictionary:
dictionary[key].append(value)
else:
dictionary[key] = [value]
This will make all the values lists. It's generally easier if you're consistent about your data format, not mixing strings and lists. So the result will be:
{'Bakir':['Davis'], 'Jose': ['Stanford', 'George Town']], 'Pierce':['Berkeley']}
Assuming, as the question seems to imply, that a list is not desired if only one value is present for a key, a simple flattening post-step can be used to achieve the specified result.
from collections import defaultdict
d = defaultdict(list)
for k, v in zip(last_names, university):
d[k].append(v)
# flatten single entry lists back to a string
d = { k: v[0] if len(v) == 1 else v for k, v in d.items() }
Try this:
my_dict = {}
for key, value in zip(last_names, university):
if key in my_dict:
old_value = my_dict[key]
if isinstance (old_value, str):
my_dict[key] = [old_value, value]
else:
old_value.add (value)
else:
my_dict[key] = value

How to find common keys in a list of dicts and sort them by value?

I want to create a finalDic which contains common keys and sum of their values
myDic = [{2:1, 3:1, 5:2}, {3:4, 6:4, 2:3}, {2:5, 3:6}, ...]
First find common keys
commonkey = [{2:1, 3:1}, {2:3, 3:4}, {2:5, 3:6}]
Then Sum and sort by their values
finalDic= {3:11, 2,9}
I've tried this and not even close what i want
import collections
myDic = [{2:1, 3:1, 5:2}, {3:4, 6:4, 2:3}, {2:5, 3:6}]
def commonKey(x):
i=0
allKeys = []
while i<len(x):
for key in x[0].keys():
allKeys.append(key)
i=i+1
commonKeys = collections.Counter(allKeys)
commonKeys = [i for i in commonKeys if commonKeys[i]>len(x)-1]
return commonKeys
print commonKey(myDic)
Thanks
Here's how I'd do it:
my_dict = [{2:1, 3:1, 5:2}, {3:4, 6:4, 2:3}, {2:5, 3:6}]
# Finds the common keys
common_keys = set.intersection(*map(set, my_dict))
# Makes a new dict with only those keys and sums the values into another dict
summed_dict = {key: sum(d[key] for d in my_dict) for key in common_keys}
Or as a crazy one-liner:
{k: sum(d[k] for d in my_dict) for k in reduce(set.intersection, map(set, my_dict))}
Only some pointers:
obtain the keys from each directory in turn them into a set() and calculate the
intersection() or all key sets. This will give you the common keys.
now iterating over the original data and summing up the matching values from each dict
is straight forward
The implementation is left to the OP as an exercise.
l = [{2:1, 3:1, 5:2}, {3:4, 6:4, 2:3}, {2:5, 3:6}]
new_dict = {}
def unique_key_value(a,b):
return set(a).intersection(set(b))
def dict_sum(k, v):
if k not in new_dict.keys():
new_dict[k] = v
else:
new_dict[k] = new_dict[k] + v
for i in reduce(unique_key_value, l):
for k in l:
if i in k.keys():
dict_sum(i, k[i])
print new_dict
hope this helps. :)
python 3.2
from collections import defaultdict
c=defaultdict(list)
for i in myDic:
for m,n in i.items():
c[m].append(n)
new_dic={i:sum(v) for i,v in c.items()if len(v)==len(myDic)}
print(new_dic)

Deleting from dict if found in new list in Python

Say I have a dictionary with whatever number of values.
And then I create a list.
If any of the values of the list are found in the dictionary, regardless of whether or not it is a key or an index how do I delete the full value?
E.g:
dictionary = {1:3,4:5}
list = [1]
...
dictionary = {4:5}
How do I do this without creating a new dictionary?
for key, value in list(dic.items()):
if key in lst or value in lst:
del dic[key]
No need to create a separate list or dictionary.
I interpreted "whether or not it is a key or an index" to mean "whether or not it is a key or a value [in the dictionary]"
it's a bit complicated because of your "values" requirement:
>>> dic = {1: 3, 4: 5}
>>> ls = set([1])
>>> dels = []
>>> for k, v in dic.items():
if k in ls or v in ls:
dels.append(k)
>>> for i in dels:
del dic[i]
>>> dic
{4: 5}
A one liner to do this would be :
[dictionary.pop(x) for x in list if x in dictionary.keys()]
dictionary = {1:3,4:5}
list = [1]
for key in list:
if key in dictionary:
del dictionary[key]
>>> dictionary = {1:3,4:5}
>>> list = [1]
>>> for x in list:
... if x in dictionary:
... del(dictionary[x])
...
>>> dictionary
{4: 5}
def remKeys(dictionary, list):
for i in list:
if i in dictionary.keys():
dictionary.pop(i)
return dictionary
I would do something like:
for i in list:
if dictionary.has_key(i):
del dictionary[i]
But I am sure there are better ways.
A few more testcases to define how I interpret your question:
#!/usr/bin/env python
def test(beforedic,afterdic,removelist):
d = beforedic
l = removelist
for i in l:
for (k,v) in list(d.items()):
if k == i or v == i:
del d[k]
assert d == afterdic,"d is "+str(d)
test({1:3,4:5},{4:5},[1])
test({1:3,4:5},{4:5},[3])
test({1:3,4:5},{1:3,4:5},[9])
test({1:3,4:5},{4:5},[1,3])
If the dictionary is small enough, it's easier to just make a new one. Removing all items whose key is in the set s from the dictionary d:
d = dict((k, v) for (k, v) in d.items() if not k in s)
Removing all items whose key or value is in the set s from the dictionary d:
d = dict((k, v) for (k, v) in d.items() if not k in s and not v in s)

Categories