Dictionary rearrangement and sorting - python

Required of counting the number of different values appear in the dict books, and in accordance with the number of occurrences of value reverse output.
books = {
123457889: 'A',
252435234: 'A',
434234341: 'B',
534524365: 'C',
354546589: 'D',
146546547: 'D',
353464543: 'F',
586746547: 'E',
511546547: 'F',
546546647: 'F',
541146127: 'F',
246546127: 'A',
434545127: 'B',
533346127: 'E',
544446127: 'F',
546446127: 'G',
155654627: 'G',
546567627: 'G',
145452437: 'H',
}
Output like this:
'F': 5,
'A': 3,
'G': 3,
'B': 2,
'D': 2,
'E': 2,
'C': 1,
'H': 1
I tried it:
import pprint
# to get the values from books
clist = [v for v in books.values()]
# values in books as keys in count,
count = {}
for c in clist:
count.setdefault(c, 0)
count[c] += 1
pprint.pprint(count)
But dict couldn't sorting.

Your code works fine. You can do this much easier using Counter from the collections module to do this for you. Simply pass books.values() in to Counter:
from collections import Counter
counts = Counter(books.values())
print(counts)
Output:
Counter({'F': 5, 'A': 3, 'G': 3, 'E': 2, 'D': 2, 'B': 2, 'H': 1, 'C': 1})
To provide the layout of the output you are expecting in order of value, you can perform a simple iteration using the most_common method and print each line:
for char, value in counts.most_common():
print("'{}': {}".format(char, value))
Output:
'F': 5
'G': 3
'A': 3
'E': 2
'D': 2
'B': 2
'C': 1
'H': 1

Related

Comparing 2 lists of dictionaries and adding a key,value when a common key is identified

I have two lists of dictionaries. The first list will contain significantly more dictionaries than the second list. There could be up to 200-300 dictionaries in list1 and no more than 10-15 dictionaries in list2.
For example, any dictionary in list1 that has the same 'g': h key/value as that of list2 needs to add key/value 'j': k to list 1.
list1 = [{'a': b, 'c': d, 'e': f, 'g': h},
{'a': b, 'c': d, 'e': f, 'g': h},
{'a': b, 'c': d, 'e': f, 'g': h},
{'a': b, 'c': d, 'e': f, 'g': h}
]
list2 = [{'g': h, 'j': k}]
I'm struggling on finding any previous examples of this type and cannot figure out a function of my own.
A trivial implementation could be:
for d1 in list1:
for d2 in list2:
if any(pair in d1.items() for pair in d2.items()):
d1.update(d2)
The value of list1 after this transformation:
[{'a': 'b', 'c': 'd', 'e': 'f', 'g': 'h', 'j': 'k'},
{'a': 'b', 'c': 'd', 'e': 'f', 'g': 'h', 'j': 'k'},
{'a': 'b', 'c': 'd', 'e': 'f', 'g': 'h', 'j': 'k'},
{'a': 'b', 'c': 'd', 'e': 'f', 'g': 'h', 'j': 'k'}]

Merging Key-Value Pairings in Dictionary

I have a dictionary that consists of employee-manager as key-value pairs:
{'a': 'b', 'b': 'd', 'c': 'd', 'd': 'f'}
I want to show the relations between employee-manager at all levels (employee's boss, his boss's boss, his boss's boss's boss etc.) using a dictionary. The desired output is:
{'a': [b,d,f], 'b': [d,f], 'c': [d,f], 'd': [f] }
Here is my attempt which only shows the first level:
for key, value in data.items():
if (value in data.keys()):
data[key] = [value]
data[key].append(data[value])
I can do another conditional statement to add the next level but this would be the wrong way to go about it. I'm not very familiar with dictionaries so what would be a better approach?
>>> D = {'a': 'b', 'b': 'd', 'c': 'd', 'd': 'f'}
>>> res = {}
>>> for k in D:
... res[k] = [j] = [D[k]]
... while j in D:
... j = D[j]
... res[k].append(j)
...
>>> res
{'b': ['d', 'f'], 'c': ['d', 'f'], 'd': ['f'], 'a': ['b', 'd', 'f']}
You may use the concept of recursion as :
def get_linked_list(element, hierarchy, lst):
if element:
lst.append(element)
return get_linked_list(hierarchy.get(element, ""), hierarchy, lst)
else:
return lst
And then access the hierarchy as:
>>> d = {'a': 'b', 'b': 'd', 'c': 'd', 'd': 'f'}
>>> print {elem:get_linked_list(elem, d, [])[1:] for elem in d.keys()}
>>> {'a': ['b', 'd', 'f'], 'c': ['d', 'f'], 'b': ['d', 'f'], 'd': ['f']}
However care must be taken as this may get to an infinite loop if we have an item in the dictionary as "a": "a"
x={'a': 'b', 'b': 'd', 'c': 'd', 'd': 'f'}
d={}
l=x.keys()
for i in l:
d.setdefault(i,[])
d[i].append(x[i])
for j in l[l.index(i)+1:]:
if j==d[i][-1]:
d[i].append(x[j])
print d
Output:{'a': ['b', 'd', 'f'], 'c': ['d', 'f'], 'b': ['d', 'f'], 'd': ['f']}

Dictionary as value in dictionary

There is a dictionary with dictionaries as the value inside like so:
{'a': {'b': 'c', 'd': 'e', 'f': 'g'}, 'h': {'i': 'j', 'k': 'l', 'm': 'n'}}
How is it possible to access, let's say; the 'f' key (producing 'g') for 'a'?
Just chain key look-ups:
outer_dictionary['a']['f']
Here dictionary['a'] returns the value for the key 'a', which is itself a dictionary.
You could also store the intermediary result:
nested_dictionary = outer_dictionary['a']
nested_dictionary['f']
This does the exact same thing, but also leaves another reference to the nested dictionary available as nested_dictionary.
Quick demo:
>>> nested_dictionary = {'a': {'b': 'c', 'd': 'e', 'f': 'g'}, 'h': {'i': 'j', 'k': 'l', 'm': 'n'}}
>>> nested_dictionary['a']
{'b': 'c', 'd': 'e', 'f': 'g'}
>>> nested_dictionary['a']['f']
'g'

Generate a Dictionary using two lists

I have two lists like so:
listA = [a, b, c, d, e, f, g]
listB = [g, h, i, j, k, l]
I have the following function
def genOneDic(dic1, dic2):
I would like to do something like return a joined single dic something like
dict(( e, dic1.get(e)) for e in listA) + dict(( e, dic2.get(e)) for e in listB)
That seems wrong, what's the right way to do that?
Example with dic1
dic1 = {'a':'1', 'b':'2', 'c':'3', 'd':'4', 'e':'5', 'f':'6', 'x':'10', 'z':'11'}
listA = ['a', 'b', 'c', 'd', 'e', 'f']
dict(( e, dic1.get(e)) for e in listA)
should return get only the fields in listA. Now when joining both listA and listB have a 'g', but they should be different in the single dic. There should be two 'g's. Would the best solution be to just prepend dic1 or dic2 to the keys and the join the dic?
Here is how you would create a dict that skips overlapped keys in two lists.
Use the set intersection to find the keys in both lists:
listA = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
listB = ['g', 'h', 'i', 'j', 'k', 'l']
di={k:v for v,k in enumerate(listA,1) if k not in set(listA) & set(listB)}
i=max(di.values())
di.update({k:v for v,k in enumerate(listB,i) if k not in set(listA) & set(listB)})
i=max(di.values())
print di
# {'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4, 'f': 6, 'i': 8, 'h': 7, 'k': 10, 'j': 9, 'l': 11}
Then reuse the set intersection to create the two keys for the overlapping keys. In this step, you might loose order of some of the keys in the overlap since sets are unordered:
for e in set(listA) & set(listB):
di['listA.'+e]=max(di.values())+1
di['listB.'+e]=max(di.values())+1
print di
# {'a': 1, 'listB.g': 13, 'c': 3, 'b': 2, 'e': 5, 'd': 4, 'f': 6, 'i': 8, 'h': 7, 'k': 10, 'j': 9, 'l': 11, 'listA.g': 12}
You can use the same technique to interleave two list and dicts:
listA = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
listB = ['g', 'h', 'i', 'j', 'k', 'l']
dic1 = {'a':'1', 'b':'2', 'c':'3', 'd':'4', 'e':'5', 'f':'6', 'g':'10', 'z':'11'}
dic2 = {'g':'55', 'h':'56', 'i':'56', 'j':'57', 'k':'58', 'l':'59', 'x':'10', 'z':'11'}
di={k:dic1.get(k, None) for k in listA if k not in set(listA) & set(listB)}
di.update({k:dic2.get(k, None) for k in listB if k in set(listB)-set(listA) and k not in set(listA) & set(listB)})
for e in set(listA) & set(listB):
di['dic1.'+e]=dic1.get(e, None)
di['dic2.'+e]=dic2.get(e, None)
print di
# {'a': '1', 'c': '3', 'b': '2', 'e': '5', 'd': '4',
'f': '6', 'i': '56', 'h': '56', 'k': '58', 'j': '57',
'l': '59', 'dic1.g': '10', 'dic2.g': '55'}
Your question is vague, but I think this is what you are looking for.
first = {k: dic1.get(k) for k in listA }
second = {k: dic2.get(k) for k in listB }
first.update(second)

Python count in a sublist in a nest list

x = [['a', 'b', 'c'], ['a', 'c', 'd'], ['e', 'f', 'f']]
Let's say we have a list with random str letters.
How can i create a function so it tells me how many times the letter 'a' comes out, which in this case 2. Or any other letter, like 'b' comes out once, 'f' comes out twice. etc.
Thank you!
You could flatten the list and use collections.Counter:
>>> import collections
>>> x = [['a', 'b', 'c'], ['a', 'c', 'd'], ['e', 'f', 'f']]
>>> d = collections.Counter(e for sublist in x for e in sublist)
>>> d
Counter({'a': 2, 'c': 2, 'f': 2, 'b': 1, 'e': 1, 'd': 1})
>>> d['a']
2
import itertools, collections
result = collections.defaultdict(int)
for i in itertools.chain(*x):
result[i] += 1
This will create result as a dictionary with the characters as keys and their counts as values.
Just FYI, you can use sum() to flatten a single nested list.
>>> from collections import Counter
>>>
>>> x = [['a', 'b', 'c'], ['a', 'c', 'd'], ['e', 'f', 'f']]
>>> c = Counter(sum(x, []))
>>> c
Counter({'a': 2, 'c': 2, 'f': 2, 'b': 1, 'e': 1, 'd': 1})
But, as Blender and John Clements have addressed, itertools.chain.from_iterable() may be more clear.
>>> from itertools import chain
>>> c = Counter(chain.from_iterable(x)))
>>> c
Counter({'a': 2, 'c': 2, 'f': 2, 'b': 1, 'e': 1, 'd': 1})

Categories

Resources