Write dictionary to text file with newline - python

I have a python dictionary {'A': '1', 'B': '2', 'C': '3'}. I want to write this dictionary into a file. This is how I did it;
test_dict = {'A': '1', 'B': '2', 'C': '3'}
f = open("dict.txt", "w")
f.write(str(test_dict))
f.close()
However, what I want the text file is to look like this;
{
'A': '1',
'B': '2',
'C': '3',
}
How do I add the newline when writing to the text file?
I am using python 3.7

The str() method for a dict return it as a single line print, so if you want to format your output, iterate over the dict and write in the file the way you want.
test_dict = {'A': '1', 'B': '2', 'C': '3'}
f = open("dict.txt", "w")
f.write("{\n")
for k in test_dict.keys():
f.write("'{}':'{}'\n".format(k, test_dict[k]))
f.write("}")
f.close()

This method uses F-string which results in more readable code. F-string is supported in python v3, not v2
f = open("dict.txt", "w")
f.write("{\n")
for k in test_dict.keys():
f.write(F"'{k}': '{test_dict[k]}',\n") # add comma at end of line
f.write("}")
f.close()

Related

How can I create a list of dictionaries from a csv file?

I want to create a "dictionary of dictionaries" for each row of the following csv file
name,AGATC,AATG,TATC
Alice,2,8,3
Bob,4,1,5
Charlie,3,2,5
So the idea is, that mydict["Alice"] should be {'AGATC': 2, 'AATG': 8, 'TATC': 3} etc.
I really do not understand the .reader and .DictReader functions sufficiently. https://docs.python.org/3/library/csv.html#csv.DictReader
Because I am a newbie and cannot quite understand the docs. Do you have other 'easier' resources, that you can recommend?
First, I have to get the first column, i.e. names and put them as keys. How can I access that first column?
Second, I want to create a dictionary inside that name (as the value), with the keys being AGATC,AATG,TATC. Do you understand what I mean? Is that possible?
Edit, made progess:
# Open the CSV file and read its contents into memory.
with open(argv[1]) as csvfile:
reader = list(csv.reader(csvfile))
# Each row read from the csv file is returned as a list of strings.
# Establish dicts.
mydict = {}
for i in range(1, len(reader)):
print(reader[i][0])
mydict[reader[i][0]] = reader[i][1:]
print(mydict)
Out:
{'Alice': ['2', '8', '3'], 'Bob': ['4', '1', '5'], 'Charlie': ['3', '2', '5']}
But how to implement nested dictionaries as described above?
Edit #3:
# Open the CSV file and read its contents into memory.
with open(argv[1]) as csvfile:
reader = list(csv.reader(csvfile))
# Each row read from the csv file is returned as a list of strings.
# Establish dicts.
mydict = {}
for i in range(1, len(reader)):
print(reader[i][0])
mydict[reader[i][0]] = reader[i][1:]
print(mydict)
print(len(reader))
dictlist = [dict() for x in range(1, len(reader))]
#for i in range(1, len(reader))
for i in range(1, len(reader)):
dictlist[i-1] = dict(zip(reader[0][1:], mydict[reader[i][0]]))
#dictionary = dict(zip(reader[0][1:], mydict[reader[1][0]]))
print(dictlist)
Out:
[{'AGATC': '2', 'AATG': '8', 'TATC': '3'}, {'AGATC': '4', 'AATG': '1', 'TATC': '5'}, {'AGATC': '3', 'AATG': '2', 'TATC': '5'}]
{'AGATC': 1, 'AATG': 1, 'TATC': 5}
So I solved it for myself:)
The following code will give you what you've asked for in terms of dict struture.
import csv
with open('file.csv', newline='') as csvfile:
mydict = {}
reader = csv.DictReader(csvfile)
# Iterate through each line of the csv file
for row in reader:
# Create the dictionary structure as desired.
# This uses a comprehension
# Foreach item in the row get the key and the value except if the key
# is 'name' (k != 'name')
mydict[row['name']] = { k: v for k, v in row.items() if k != 'name' }
print(mydict)
This will give you
{
'Alice': {'AGATC': '2', 'AATG': '8', 'TATC': '3'},
'Bob': {'AGATC': '4', 'AATG': '1', 'TATC': '5'},
'Charlie': {'AGATC': '3', 'AATG': '2', 'TATC': '5'}
}
There are plenty of videos and articles covering comprehensions on the net if you need more information on these.

How to use a dict comprehension to split a list?

I currently have a dict in the form:
data = {"var1":"600103", "var2":[{"a":"1","b":"2"}]}
I would like the output to be:
op = {"var1":"600103","var2[0]":{"a":"1","b":"2"}}
I am currently using loops to manually loop through. I'd like to know if there's a more pythonic way of doing this.
If this isn't what you're already doing, you can eliminate the need for a nested loop by using a dict comprehension for the values which are lists.
data = {"var1":"600103", "var2":[{"a":"1","b":"2"}, {"a":"22","b":"555"}]}
op = {}
for k in data:
if not isinstance(data[k], list):
op[k] = data[k]
else:
op.update({k + '[{}]'.format(i) : data[k][i] for i in range(len(data[k])) })
And, your output will look like this:
{'var1': '600103', 'var2[1]': {'a': '22', 'b': '555'}, 'var2[0]': {'a': '1', 'b': '2'}}
I do not know if it is very pythonic or not but I know for sure that it is difficult to read :S
Sorry, just playing... ;)
data = {"var1":"600103", "var2":[{"a":"1","b":"2"},{"a":"3","b":"4"},{"a":"5","b":"6"},{"a":"7","b":"8"}], "var3":"600103"}
reduce(
lambda a, b: dict(a.items() + b.items()),
[
dict(map(lambda (idx, i): ('{0}[{1}]'.format(key, idx), i), enumerate(value))) if type(value) is list else {key: value}
for key, value
in data.items()
]
)
output:
{'var1': '600103',
'var2[0]': {'a': '1', 'b': '2'},
'var2[1]': {'a': '3', 'b': '4'},
'var2[2]': {'a': '5', 'b': '6'},
'var2[3]': {'a': '7', 'b': '8'},
'var3': '600103'}

Converting colon separated list into a dict?

I wrote something like this to convert comma separated list to a dict.
def list_to_dict( rlist ) :
rdict = {}
i = len (rlist)
while i:
i = i - 1
try :
rdict[rlist[i].split(":")[0].strip()] = rlist[i].split(":")[1].strip()
except :
print rlist[i] + ' Not a key value pair'
continue
return rdict
Isn't there a way to
for i, row = enumerate rlist
rdict = tuple ( row )
or something?
You can do:
>>> li=['a:1', 'b:2', 'c:3']
>>> dict(e.split(':') for e in li)
{'a': '1', 'c': '3', 'b': '2'}
If the list of strings require stripping, you can do:
>>> li=["a:1\n", "b:2\n", "c:3\n"]
>>> dict(t.split(":") for t in map(str.strip, li))
{'a': '1', 'b': '2', 'c': '3'}
Or, also:
>>> dict(t.split(":") for t in (s.strip() for s in li))
{'a': '1', 'b': '2', 'c': '3'}
If I understand your requirements correctly, then you can use the following one-liner.
def list_to_dict(rlist):
return dict(map(lambda s : s.split(':'), rlist))
Example:
>>> list_to_dict(['alpha:1', 'beta:2', 'gamma:3'])
{'alpha': '1', 'beta': '2', 'gamma': '3'}
You might want to strip() the keys and values after splitting in order to trim white-space.
return dict(map(lambda s : map(str.strip, s.split(':')), rlist))
You mention both colons and commas so perhaps you have a string with key/values pairs separated by commas, and with the key and value in turn separated by colons, so:
def list_to_dict(rlist):
return {k.strip():v.strip() for k,v in (pair.split(':') for pair in rlist.split(','))}
>>> list_to_dict('a:1,b:10,c:20')
{'a': '1', 'c': '20', 'b': '10'}
>>> list_to_dict('a:1, b:10, c:20')
{'a': '1', 'c': '20', 'b': '10'}
>>> list_to_dict('a : 1 , b: 10, c:20')
{'a': '1', 'c': '20', 'b': '10'}
This uses a dictionary comprehension iterating over a generator expression to create a dictionary containing the key/value pairs extracted from the string. strip() is called on the keys and values so that whitespace will be handled.

How can I replace certain characters in a string?

I'm relatively new to python(3.5.2) and I'd love some help with my assignment on lists& strings.
I am required to write a code that replaces: e and E with 3, a and A with 4, i and I with 1, o and O with 0 in any given string. Here is my attempt:
s = input("Enter a string: ")
leet = {'a':'4','e':'3','i':'1','o':'0','A':'4','E':'3','I':'1','O':'0'}
for character in s:
if character == leet.keys():
str.replace(leet.keys(),leet.values())
print(s)
This code does not yield any satisfying results for me, I'm wondering if I can use the str.replace method or is there any easier way of doing this?
Thanks!
you can do that in one line using a generator comprehension converted to a string using str.join (Using dict.get with defaults to the input character if not found in dictionary):
s = "a string Entered"
leet = {'a':'4','e':'3','i':'1','o':'0','A':'4','E':'3','I':'1','O':'0'}
crypted = "".join(leet.get(k,k) for k in s)
print(crypted)
result:
4 str1ng 3nt3r3d
replace() method is good. But you use it wrong. Remember that leet.keys() will return a list of all keys in the dictionary. So I suggest this:
s = input("Enter a string: ")
leet = {'a': '4', 'e': '3', 'i': '1', 'o': '0', 'A': '4', 'E': '3', 'I': '1', 'O': '0'}
for k, v in leet.items(): #iterating through dictionary (not string)
s = s.replace(k, v)
print(s)

Adding dictionary keys and values after line split?

If I have for instance the file:
;;;
;;;
;;;
A 1 2 3
B 2 3 4
C 3 4 5
And I want to read it into a dictionary of {str: list of str} :
{'A': ['1', '2', '3'], 'B': ['2', '3', '4'], 'C': ['3', '4', '5']
I have the following code:
d = {}
with open('file_name') as f:
for line in f:
while ';;;' not in line:
(key, val) = line.split(' ')
#missingcodehere
return d
What should I put in after the line.split to assign the keys and values as a str and list of str?
To focus on your code and what you are doing wrong.
You are pretty much in an infinite loop with your while ';;;' not in line. So, you want to change your logic with how you are trying to insert data in to your dictionary. Simply use a conditional statement to check if ';;;' is in your line.
Then, when you get your key and value from your line.strip().split(' ') you simply just assign it to your dictionary as d[key] = val. However, you want a list, and val is currently a string at this point, so call split on val as well.
Furthermore, you do not need to have parentheses around key and val. It provides unneeded noise to your code.
The end result will give you:
d = {}
with open('new_file.txt') as f:
for line in f:
if ';;;' not in line:
key, val = line.strip().split(' ')
d[key] = val.split()
print(d)
Using your sample input, output is:
{'C': ['3', '4', '5'], 'A': ['1', '2', '3'], 'B': ['2', '3', '4']}
Finally, to provide an improvement to the implementation as it can be made more Pythonic. We can simplify this code and provide a small improvement to split more generically, rather than counting explicit spaces:
with open('new_file.txt') as fin:
valid = (line.split(None, 1) for line in fin if ';;;' not in line)
d = {k:v.split() for k, v in valid}
So, above, you will notice our split looks like this: split(None, 1). Where we are providing a maxsplit=1.
Per the docstring of split, it explains it pretty well:
Return a list of the words in S, using sep as the
delimiter string. If maxsplit is given, at most maxsplit
splits are done. If sep is not specified or is None, any
whitespace string is a separator and empty strings are
removed from the result.
Finally, we simply use a dictionary comprehension to obtain our final result.
Why not simply:
def make_dict(f_name):
with open(f_name) as f:
d = {k: v.split()
for k, v in [line.strip().split(' ')
for line in f
if ';;;' not in line]}
return d
Then
>>> print(make_dict('file_name'))
{'A': ['1', '2', '3'], 'B': ['2', '3', '4'], 'C': ['3', '4', '5']}

Categories