Finding the second level keys of a multi key dictionary Python? - python

I have a multi key dict in the following format. I am trying to access the list of the second level keys, however, it is returning the keys in the format of a dict_keys list. What I am trying to get is ['a', 'b', 'c', 'd', 'e', 'f']
dictTest={}
dictTest[1]={'a':1, 'b':2}
dictTest[2]={'c':1, 'd':2}
dictTest[3]={'e':1, 'f':2}
print(dictTest)
print(list([dictTest[i].keys() for i in dictTest.keys()]))
{1: {'a': 1, 'b': 2}, 2: {'c': 1, 'd': 2}, 3: {'e': 1, 'f': 2}}
[dict_keys(['a', 'b']), dict_keys(['c', 'd']), dict_keys(['e', 'f'])]

You could use itertools.chain in combination with mapping dict.keys to all the dicts values:
from itertools import chain
dictTest = {1: {'a': 1, 'b': 2}, 2: {'c': 1, 'd': 2}, 3: {'e': 1, 'f': 2}}
print(list(chain(*map(dict.keys, dictTest.values()))))
['a', 'b', 'c', 'd', 'e', 'f']

>>> [v2 for v1 in dictTest.values() for v2 in v1]
['a', 'b', 'c', 'd', 'e', 'f']

Try this:
# sum([list(b.keys()) for b in dictTest.values()], [])
# syntax improvement by #wwii
sum([list(b) for b in dictTest.values()], [])
Output:
['a', 'b', 'c', 'd', 'e', 'f']

Related

Extract all possible combinations of unique elements in dict of lists

I have this input:
d = {'a': ['A', 'B', 'C'], 'b': ['A', 'B', 'C'], 'c': ['D', 'E'], 'd': ['E', 'F', 'G']}
How can I extract all the possible unique samplings per list?
One of the possible output is for example:
d = {'a': 'A', 'b': 'B', 'c': 'D', 'd': 'E'}
or
d = {'a': 'B', 'b': 'A', 'c': 'E', 'd': 'F'}
and so on..
Any idea?
Thank you
This is what you are looking for
import itertools
keys, values = zip(*d.items())
permutations_dicts = [dict(zip(keys, v)) for v in itertools.product(*values)]

Replace placeholder in string with dictionary keys

Let's assume I have:
a placeholder string "aabbaaa"
and a dictionary: {'A': 'a', 'B': 'a', 'C': 'b', 'D': 'a', 'E': 'b', 'F': 'a', 'G': 'b'}.
How can I create in python all possible permutations from the dictionary keys for the placeholder string?
The expected result would, for example, be:
AACCAAA, AACCAAB, AACCABA, ... AACEAA, AACEAA, AAEEAA ... , FFGGFFF etc.
The solution could be:
>>> import itertools
>>> from collections import defaultdict
>>> dict_ = defaultdict(list)
>>> input = "ab"
>>> _dict = {'A': 'a', 'B': 'a', 'C': 'b', 'D': 'a', 'E': 'b', 'F': 'a', 'G': 'b'}
>>> for k,v in _dict.items():
... dict_[v].append(k)
...
>>> _iterables = [dict_[character] for character in input]
>>> output = [''.join(tup) for tup in itertools.product(*_iterables)]
set(['BE', 'AC', 'BG', 'AE', 'AG', 'BC', 'DG', 'DE', 'DC', 'FC', 'FE', 'FG'])
Let me know if it helps!!
You can build all the permutation with backtracking.
At first the dict would be more useful if reversed, so do it:
from collections import defaultdict
orig_str = "aabbaaa"
d = {'A': 'a', 'B': 'a', 'C': 'b', 'D': 'a', 'E': 'b', 'F': 'a', 'G': 'b'}
reverse_d = defaultdict(list)
for k, el in d.items():
reverse_d[el].append(k)
And here we have reverse_d = {'a': ['A', 'B', 'D', 'F'], 'b': ['C', 'E', 'G']}
Next we can write our backtracking function that for any character of the string will put the possibilities in order:
def permut(orig_str, index, chars_till_now):
if index == len(orig_str):
print("".join(chars_till_now))
return
chars = chars_till_now[:]
chars.append("")
for possibility in reverse_d[orig_str[index]]:
chars[-1] = possibility
permut(orig_str, index+1, chars)
You can modify the function to save the permutation rather than print or pass a specific dictionary rather than use one global; it depends on what you need.
To call the function just:
permut(orig_str, 0, [])

How to count the occurance of all elements of list in python?

I have to write all the elements separately along with their count.
It's the program i have made. It is counting correctly but not giving required output
The output is like this
I want output to be like this. All digits showing individual complete count
You can count the number of occurrence of a special element with count() method:
grades = ['b', 'b', 'f', 'c', 'b', 'a', 'a', 'd', 'c', 'd', 'a', 'a', 'b']
letters = ['a', 'b', 'c', 'd', 'f']
print(list(map(lambda letter: {letter: grades.count(letter)}, letters)))
Output:
[{'a': 4}, {'b': 4}, {'c': 2}, {'d': 2}, {'f': 1}]
If you want to do this without using letters. you can do this:
grades = ['b', 'b', 'f', 'c', 'b', 'a', 'a', 'd', 'c', 'd', 'a', 'a', 'b']
print(list(map(lambda letter: {letter: grades.count(letter)}, set(grades))))
Output:
[{'f': 1}, {'b': 4}, {'c': 2}, {'d': 2}, {'a': 4}]
For your expected output:
grades = ['b', 'b', 'f', 'c', 'b', 'a', 'a', 'd', 'c', 'd', 'a', 'a', 'b']
occurrence = map(lambda letter: (letter, grades.count(letter)), set(grades))
for item in occurrence:
print(f"{item[0]}={item[1]}")
Output:
c=2
b=4
d=2
f=1
a=4
Update
You can use defaultdict() to count the occurrence of each element:
from collections import defaultdict
grades = ['b', 'b', 'f', 'c', 'b', 'a', 'a', 'd', 'c', 'd', 'a', 'a', 'b']
occurrence = defaultdict(lambda: 0)
for character in grades:
occurrence[character] += 1
for key, value in occurrence.items():
print(f"{key}={value}")
Output:
b=4
f=1
c=2
a=4
d=2

Custom list of lists into dictionary

I have list of lists and I wish to create a dictionary with length of each element as values. I tried the following:
tmp = [['A', 'B', 'E'], ['B', 'E', 'F'], ['A', 'G']]
tab = []
for line in tmp:
tab.append(dict((k, len(tmp)) for k in line))
But it gives the output as:
[{'A': 3, 'B': 3, 'E': 3}, {'B': 3, 'E': 3, 'F': 3}, {'A': 3, 'G': 3}]
What is the modification that I should make to get the output:
{['A', 'B', 'E']:3, ['B', 'E', 'F']:3, ['A', 'G']:2}
Thanks in advance.
AP
You can't use list objects as dictionary keys, they are mutable and unhashable. You can convert them to tuple. Also note that you are looping over each sub list. You can use a generator expression by only looping over the main list:
In [3]: dict((tuple(sub), len(sub)) for sub in tmp)
Out[3]: {('A', 'B', 'E'): 3, ('A', 'G'): 2, ('B', 'E', 'F'): 3}
{tuple(t):len(t) for t in tmp}
Input :
[['A', 'B', 'E'], ['B', 'E', 'F'], ['A', 'G']]
Output :
{('A', 'G'): 2, ('A', 'B', 'E'): 3, ('B', 'E', 'F'): 3}
Dictionnary does not accept list as key, but tuple

Remove elements from nested list - Python

data = [['A', 'B', 'C', 'D'],
['E', 'F', 'G'],
['I', 'J'],
['A', 'B', 'C', 'E', 'F']]
I would like to remove unpopular elements (appearing only once) from the lists. So the results should look like this:
data = [['A', 'B', 'C'],
['E', 'F'],
['A', 'B', 'C', 'E', 'F']]
I was able to count the frequency of each element using the following codes:
from collections import Counter
Counter(x for sublist in data for x in sublist)
#output
Counter({'A': 2, 'C': 2, 'B': 2, 'E': 2, 'F': 2, 'D': 1, 'G': 1, 'I': 1, 'J': 1})
However, I am not sure how to use this count information to remove unpopular elements from the list. Any help?
Generate the new list based on the frequency information.
The following code uses nested list comprehension to do that:
from collections import Counter
freq = Counter(x for sublist in data for x in sublist)
data = [[x for x in row if freq[x] > 1] for row in data] # Remove non-popular item
data = [row for row in data if row] # Remove empty rows
# data => [['A', 'B', 'C'], ['E', 'F'], ['A', 'B', 'C', 'E', 'F']]
The complexity is similar. Just use map and filter function to make the code more pythonic.
from collections import Counter
data = [['A', 'B', 'C', 'D'],
['E', 'F', 'G'],
['I', 'J'],
['A', 'B', 'C', 'E', 'F']]
counter = Counter({'A': 2, 'C': 2, 'B': 2, 'E': 2, 'F': 2, 'D': 1, 'G': 1, 'I': 1, 'J': 1})
result = map(lambda row: filter(lambda x: counter.get(x) > 1, row), data)
print result

Categories