Print nested dictionary in python3 - python-3.x

How can I print a nested python dictionary in a specific format?
So, my dictionary is looks like this:
dictionary = {'Doc1':{word1: 3, word2: 1}, 'Doc2':{word1: 1, word2: 14, word3: 3}, 'Doc3':{word1: 2}}
I tried the following way:
for x, y in dictionary.items():
print(x,":", y)
But it will printL`
Doc1: {word1:3, word2: 1}
Doc2: {word1:1, word2:14, word3:3}
Doc3: {word1:2}
How to get rid of the bracket and print the plain information?
I want to print on the following format:
Doc1: word1:3; word2:1
Doc2: word1:1; word2:14; word3: 3
Doc3: word1:2;
:

in your case 'y' is a dict, so if you want to print it differently you can override the repr (representation of the object) or dict.
alternatively you can use some recursion here
def print_d(dd):
if type(dd) != dict:
return str(dd)
else:
res = []
for x,y in dd.items():
res.append(''.join((str(x),':',print_d(y))))
return '; '.join(res)
if __name__=='__main__':
dictionary = {'Doc1':{'word1': 3, 'word2': 1}, 'Doc2':{'word1': 1, 'word2': 14, 'word3': 3}, 'Doc3':{'word1': 2}}
for x, y in dictionary.items():
print(x,": ", print_d(y))

Aside from the fact that your original dictionary declaration is not valid python unless each word is a defined variable, this seems to work:
import json
print(json.dumps(dictionary).replace("{","").replace(',','').replace("}","\n").replace('"',''))
Result:
Doc1: word1: 3 word2: 1
Doc2: word1: 1 word2: 14 word3: 3
Doc3: word1: 2

Related

Python: Convert 2d list to dictionary with indexes as values

I have a 2d list with arbitrary strings like this:
lst = [['a', 'xyz' , 'tps'], ['rtr' , 'xyz']]
I want to create a dictionary out of this:
{'a': 0, 'xyz': 1, 'tps': 2, 'rtr': 3}
How do I do this? This answer answers for 1D list for non-repeated values, but, I have a 2d list and values can repeat. Is there a generic way of doing this?
Maybe you could use two for-loops:
lst = [['a', 'xyz' , 'tps'], ['rtr' , 'xyz']]
d = {}
overall_idx = 0
for sub_lst in lst:
for word in sub_lst:
if word not in d:
d[word] = overall_idx
# Increment overall_idx below if you want to only increment if word is not previously seen
# overall_idx += 1
overall_idx += 1
print(d)
Output:
{'a': 0, 'xyz': 1, 'tps': 2, 'rtr': 3}
You could first convert the list of lists to a list using a 'double' list comprehension.
Next, get rid of all the duplicates using a dictionary comprehension, we could use set for that but would lose the order.
Finally use another dictionary comprehension to get the desired result.
lst = [['a', 'xyz' , 'tps'], ['rtr' , 'xyz']]
# flatten list of lists to a list
flat_list = [item for sublist in lst for item in sublist]
# remove duplicates
ordered_set = {x:0 for x in flat_list}.keys()
# create required output
the_dictionary = {v:i for i, v in enumerate(ordered_set)}
print(the_dictionary)
""" OUTPUT
{'a': 0, 'xyz': 1, 'tps': 2, 'rtr': 3}
"""
also, with collections and itertools:
import itertools
from collections import OrderedDict
lstdict={}
lst = [['a', 'xyz' , 'tps'], ['rtr' , 'xyz']]
lstkeys = list(OrderedDict(zip(itertools.chain(*lst), itertools.repeat(None))))
lstdict = {lstkeys[i]: i for i in range(0, len(lstkeys))}
lstdict
output:
{'a': 0, 'xyz': 1, 'tps': 2, 'rtr': 3}

Printing list containing a string

I am trying to store a string variable containg some names, I want to store the respective variable in a list and print it, but am unable print the values which are stored in variable.
name='vsb','siva','anand','soubhik' #variable containg some names
lis=['name'] # storing the variable in a list
for x in lis:
print(x) #printing the list using loops
Image:
Maybe dictionary? Try this
variable_1 = "aa"
variable_2 = "bb"
lis = {}
lis['name1'] = variable_1
lis['name2'] = variable_2
for i in lis:
print(i)
print(lis[i])
Your name variable is actually a tuple.
Example of tuple declaration:
tup1 = ('physics', 'chemistry', 1997, 2000)
tup2 = (1, 2, 3, 4, 5 )
tup3 = "a", "b", "c", "d"
Example of list declaration:
list1 = ['physics', 'chemistry', 1997, 2000]
list2 = [1, 2, 3, 4, 5 ]
list3 = ["a", "b", "c", "d"]
For a better understanding you should read The Python Standard Library or do a tutorial.
For your problem maybe the dictionary is the solution:
# A tuple is a sequence of immutable Python objects
name='vsb','siva','anand','soubhik'
print('Tuple: ' + str(name)) # ('vsb', 'siva', 'anand', 'soubhik')
# This is a list containing one element: 'name'
lis=['name']
print('List: ' + str(lis)) # ['name']
# Dictionry with key 'name' and vlue ('vsb','siva','anand','soubhik')
dictionary={'name':name}
print('Dictionary: ' + str(dictionary))
print('Dictionary elements:')
print(dictionary['name'])
print('Tuple elements:')
for x in name:
print(x)
print('List elements:')
for x in lis:
print(x)
Output
Tuple: ('vsb', 'siva', 'anand', 'soubhik')
List: ['name']
Dictionary: {'name': ('vsb', 'siva', 'anand', 'soubhik')}
Dictionary elements:
('vsb', 'siva', 'anand', 'soubhik')
Tuple elements:
vsb
siva
anand
soubhik
List elements:
name

Dictionary using distinct characters as values

I need to make a dictionary using the string list as keys and their distinct characters as values.
I have tried some functions and ended up with the following code but I cannot seem to add the string key into it
value=["check", "look", "try", "pop"]
print(value)
def distinct_characters(x):
for i in x:
yield dict (i=len(set(i)))
print (list(distinct_characters(value))
I would like to get
{ "check" : 4, "look" : 3, "try" : 3, "pop" : 2}
but I keep getting
{ "i" : 4, "i" : 3, "i" : 3, "i" : 2}
Well, string is itself an iterable, so don't call list on dicts instead call dict on list of tuples like below.
value=["check", "look", "try", "pop"]
print(value)
def distinct_characters(x):
for i in x:
yield (i, len(set(i)))
print(dict(distinct_characters(value)))
Output:
{'check': 4, 'look': 3, 'try': 3, 'pop': 2}
Consider the simple dictionary comprehension:
value = ["check", "look", "try", "pop"]
result = {key: len(set(key)) for key in value}
print(result)
Thanks for the replies
I needed to answer it as a function for a class exercise so I ended up using this code:
value=["check", "look", "try", "pop"]
print(value)
def distinct_characters(x):
for i in x:
yield (i, len(set(i)))
print(dict(distinct_characters(value)))
Thanks again

return dictionary of file names as keys and word lists with words unique to file as values

I am trying to write a function to extract only words unique to each key and list them in a dictionary output like {"key1": "unique words", "key2": "unique words", ... }. I start out with a dictionary. To test with I created a simple dictionary:
d = {1:["one", "two", "three"], 2:["two", "four",
"five"], 3:["one","four", "six"]}
My output should be:
{1:"three",
2:"five",
3:"six"}
I am thinking maybe split in to separate lists
def return_unique(dct):
Klist = list(dct.keys())
Vlist = list(dct.values())
aList = []
for i in range(len(Vlist)):
for j in Vlist[i]:
if
What I'm stuck on is how do I tell Python to do this: if Vlist[i][j] is not in the rest of Vlist then aList.append(Vlist[i][j]).
Thank you.
You can try something like this:
def return_unique(data):
all_values = []
for i in data.values(): # Get all values
all_values = all_values + i
unique_values = set([x for x in all_values if all_values.count(x) == 1]) # Values which are not duplicated
for key, value in data.items(): # For Python 3.x ( For Python 2.x -> data.iteritems())
for item in value: # Comparing values of two lists
for item1 in unique_values:
if item == item1:
data[key] = item
return data
d = {1:["one", "two", "three"], 2:["two", "four", "five"], 3:["one","four", "six"]}
print (return_unique(d))
result >> {1: 'three', 2: 'five', 3: 'six'}
Since a key may have more than one unique word associated with it, it makes sense for the values in the new dictionary to be a container type object to hold the unique words.
The set difference operator returns the difference between 2 sets:
>>> a = set([1, 2, 3])
>>> b = set([2, 4, 6])
>>> a - b
{1, 3}
We can use this to get the values unique to each key. Packaging these into a simple function yields:
def unique_words_dict(data):
res = {}
values = []
for k in data:
for g in data:
if g != k:
values += data[g]
res[k] = set(data[k]) - set(values)
values = []
return res
>>> d = {1:["one", "two", "three"],
2:["two", "four", "five"],
3:["one","four", "six"]}
>>> unique_words_dict(d)
{1: {'three'}, 2: {'five'}, 3: {'six'}}
If you only had to do this once, then you might be interested in the less efficeint but more consice dictionary comprehension:
>>> from functools import reduce
>>> {k: set(d[k]) - set(reduce(lambda a, b: a+b, [d[g] for g in d if g!=k], [])) for k in d}
{1: {'three'}, 2: {'five'}, 3: {'six'}}

Counter class extension

I am having a problem finding an elegant way to create a Counter() class that can:
Feed in arbitrary number of keys and return a nested dictionary based on this list of keys.
Increment for this nested dictionary is arbitrary as well.
For example:
counter = Counter()
for line in fin:
if a:
counter.incr(key1, 1)
else:
counter.incr(key2, key3, 2)
print counter
Ideally I am hoping to get the result looks like: {key1 : 20, {key2 : {key3 : 40}}}. But I am stuck in creating this arbitrary nested dictionary from list of keys. Any help is appreciated.
you can subclass dict and create your own nested structure.
here's my attempt at writing such class :
class Counter(dict):
def incr(self, *args):
if len(args) < 2:
raise TypeError, "incr() takes at least 2 arguments (%d given)" %len(args)
curr = self
keys, count = args[:-1], args[-1]
for depth, key in enumerate(keys, 1):
if depth == len(keys):
curr[key] = curr.setdefault(key, 0) + count
else:
curr = curr.setdefault(key, {})
counter = Counter()
counter.incr('key1', 1)
counter.incr('key2', 'key3', 2)
counter.incr('key1', 7)
print counter #{'key2': {'key3': 2}, 'key1': 8}
There are two possibilities.
First, you can always fake the nested-keys thing by using a flat Counter with a "key path" made of tuples:
counter = Counter()
for line in fin:
if a:
counter.incr((key1,), 1)
else:
counter.incr((key2, key3), 2)
But then you'll need to write a str-replacement—or, better, a wrapper class that implements __str__. And while you're at it, you can easily write an incr wrapper that lets you use exactly the API you wanted:
def incr(self, *args):
super().incr(args[:-1], args[-1])
Alternatively, you can build your own Counter-like class on top of a nested dict. The code for Counter is written in pure Python, and the source is pretty simple and readable.
From, your code, it looks like you don't have any need to access things like counter[key2][key3] anywhere, which means the first is probably going to be simpler and more appropriate.
The only type of value that can exist in a Counter object is an int, you will not be able to represent a nested dictionary with a Counter.
Here is one way to do this with a normal dictionary (counter = {}). First, to update increment the value for a single key:
counter[key1] = counter.setdefault(key1, 0) + 1
Or for an arbitrary list of keys to create the nested structure:
tmp = counter
for key in key_list[:-1]:
tmp = tmp.setdefault(key, {})
tmp[key_list[-1]] = tmp.setdefault(key_list[-1], 0) + 1
I would probably turn this into the following function:
def incr(counter, val, *keys):
tmp = counter
for key in keys[:-1]:
tmp = tmp.setdefault(key, {})
tmp[keys[-1]] = tmp.setdefault(keys[-1], 0) + val
Example:
>>> counter = {}
>>> incr(counter, 1, 'a')
>>> counter
{'a': 1}
>>> incr(counter, 2, 'a')
>>> counter
{'a': 3}
>>> incr(counter, 2, 'b', 'c', 'd')
>>> counter
{'a': 3, 'b': {'c': {'d': 2}}}
>>> incr(counter, 3, 'b', 'c', 'd')
>>> counter
{'a': 3, 'b': {'c': {'d': 5}}}

Resources