Python: from a text file to dictionary with keys - python

I have a text file with eight names, sorted by name, like this:
Anna
David
Dennis
Morgan
Lana
Peter
Joanna
Karen
And now I want to put them into a dictionary and add different keys to each of the name.
The names are on new lines. What I want to add to the names in the dict, are different binary numbers from 000-111.
How can I do this?
I have tried stuff like this:
with open ('tennis.txt', 'r') as f:
for line in f:
dict={}
for line in open('file.txt'):
bin[0]=next(f)
bin[1]=next(f)
bin[2]=next(f)
bin[3]=next(f)
bin[4]=next(f)
bin[5]=next(f)
bin[6]=next(f)
bin[7]=next(f)

Based on andybuckley's answer, you can get it done like this:
d = {}
f = open("tennis.txt")
for i, l in enumerate(f):
# cut the '0b' chars, so you will get your dict keys just like you want
bin_num = bin(i)[2:]
# if the key is shorter than 3 chars, add 0 to the beginning
while len(bin_num) < 3:
bin_num = '0' + bin_num
d[bin_num] = l[:-1]
f.close()
for i in sorted(d.items()):
print i
EDIT : Thanks to #pepr - remember to close the opened file.
Output:
('000', 'Anna')
('001', 'David')
('010', 'Dennis')
('011', 'Morgan')
('100', 'Lana')
('101', 'Peter')
('110', 'Joanna')
('111', 'Karen')

It's a bit hard to know what you want: I've interpreted the question as wanting to read names from a text file, and to insert each into a dict with an increasing binary key. Here's an interactive Python3 session which does that and shows the populated dictionary:
>>> d = {}
>>> for i, l in enumerate(open("tennis.txt")):
... d[bin(i)] = l[:-1]
>>> d
{'0b10': 'Dennis', '0b11': 'Morgan', '0b110': 'Joanna', '0b0': 'Anna', '0b1': 'David', '0b101': 'Peter', '0b100': 'Lana', '0b111': 'Karen'}
Note that I've used "d" rather than "dict" as the name for the dictionary variable, since I don't want the variable name to hide the class name: it's always a good idea to avoid using the same names for variables and classes, although Python will not object.

Use a dict comprehension, zfill, and enumerate:
with open('/tmp/names.txt') as f:
print({bin(k)[2:].zfill(3): v.strip() for k,v in enumerate(f)})
Prints:
{'000': 'Anna', '001': 'David', '011': 'Morgan', '010': 'Dennis', '101': 'Peter', '100': 'Lana', '110': 'Joanna', '111': 'Karen'}
If you don't know how many lines there are in the file in order to use the right number for zfill, you can just count them first:
with open(fn) as f:
i=max(ln for ln,line in enumerate(f) if line.strip())
print(i, bin(i)[2:])
fill=len(bin(i)[2:])
f.seek(0)
print({bin(k)[2:].zfill(fill): v.strip() for k,v in enumerate(f) if v.strip()})

Related

is there a way to only have a value in a list if the key appears multiple times in a file?

I'm trying to make a dictionary from items in a file. What I have now works but I was wondering if there is a way to only have a list if the key is a duplicate that has different value.so, if I have this
micheal math 2
jim chem 3
jim math 3
pam cs 4
expected output:
{micheal:[math,2],jim: [[chem,3], [math,3]], pam: [cs,4]}
actual output:
{micheal:[[math,2]],jim: [[chem,3], [math,3]], pam: [[cs,4]]}
current code:
example_dict = {}
for line in dictionary:
line = (line.strip()).split(' ')
key = line[0]
if key not in example_dict
example_dict[key] = []
example_dict[key].append(line[1:])
return example_dict
With your current solution, go over your example_dict afterward and flatten values that only have one element, e.x.:
...
example_dict = {k: (v if len(v) > 1 else v[0]) for k, v in example_dict.items()}
return example_dict
It seems like it would make a lot of sense to use dictionaries instead of tuple lists as values.
example_dict = {}
for line in dictionary:
name, subject, grade = line.strip().split() # optional, but cleaner
if name not in example_dict:
example_dict[name] = {}
example_dict[name][subject] = grade
Result:
{'micheal': {'math': '2'},
'jim': {'chem': '3', 'math': '3'},
'pam': {'cs': '4'}}

Convert python dictionary to uppercase

For some reason my code refuses to convert to uppercase and I cant figure out why. Im trying to then write the dictionary to a file with the uppercase dictionary values being inputted into a sort of template file.
#!/usr/bin/env python3
import fileinput
from collections import Counter
#take every word from a file and put into dictionary
newDict = {}
dict2 = {}
with open('words.txt', 'r') as f:
for line in f:
k,v = line.strip().split(' ')
newDict[k.strip()] = v.strip()
print(newDict)
choice = input('Enter 1 for all uppercase keys or 2 for all lowercase, 3 for capitalized case or 0 for unchanged \n')
print("Your choice was " + choice)
if choice == 1:
for k,v in newDict.items():
newDict.update({k.upper(): v.upper()})
if choice == 2:
for k,v in newDict.items():
dict2.update({k.lower(): v})
#find keys and replace with word
print(newDict)
with open("tester.txt", "rt") as fin:
with open("outwords.txt", "wt") as fout:
for line in fin:
fout.write(line.replace('{PETNAME}', str(newDict['PETNAME:'])))
fout.write(line.replace('{ACTIVITY}', str(newDict['ACTIVITY:'])))
myfile = open("outwords.txt")
txt = myfile.read()
print(txt)
myfile.close()
In python 3 you cannot do that:
for k,v in newDict.items():
newDict.update({k.upper(): v.upper()})
because it changes the dictionary while iterating over it and python doesn't allow that (It doesn't happen with python 2 because items() used to return a copy of the elements as a list). Besides, even if it worked, it would keep the old keys (also: it's very slow to create a dictionary at each iteration...)
Instead, rebuild your dict in a dict comprehension:
newDict = {k.upper():v.upper() for k,v in newDict.items()}
You should not change dictionary items as you iterate over them. The docs state:
Iterating views while adding or deleting entries in the dictionary may
raise a RuntimeError or fail to iterate over all entries.
One way to update your dictionary as required is to pop values and reassign in a for loop. For example:
d = {'abc': 'xyz', 'def': 'uvw', 'ghi': 'rst'}
for k, v in d.items():
d[k.upper()] = d.pop(k).upper()
print(d)
{'ABC': 'XYZ', 'DEF': 'UVW', 'GHI': 'RST'}
An alternative is a dictionary comprehension, as shown by #Jean-FrançoisFabre.

error in retriving dictionary keys from file in python

There are similar questions/answers on SO, but this refers to a specific error, and I have referred to the relevant SO topics to solve this, but with no luck.
The code I have seeks to retrieve lines from a text file and read them into a dictionary. It works, but as you can see below, not completely.
File
"['a', 5]"
"['b', 2]"
"['c', 3]"
"['d', 0]"
Code
def readfiletodict():
with open("testfile.txt","r",newline="") as f:
mydict={} #create a dictionary called mydict
for line in f:
(key,val) = line.split(",")
mydict[key]=val
print(mydict) #test
for keys in mydict:
print(keys) #test to see if the keys are being retrieved correctly
readfiletodict()
Desired output:
I wish the dictionary to hold keys: a,b,c,d and corresponding values as shown in the file, without the unwanted character. Simiarly, I need the values to be stored correctly in the dictionary as integers (so that they can be worked with later)
For quick replication see: https://repl.it/KgQe/0 for the whole code and problem
Current (erroneous) output:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
{'"[\'a\'': ' 5]"\r\n', '"[\'b\'': ' 2]"\r\n', '"[\'c\'': ' 3]"\r\n', '"[\'d\'': ' 0]"\r\n'}
"['a'
"['b'
"['c'
"['d'
The Stackoverflow answer I have used in my current code is from: Python - file to dictionary? but it doesn't quite work for me...
Your code slightly modified - the key is to strip out all the chars that we don't care about ([Python]: str.rstrip([chars])):
def readfiletodict():
with open("testfile.txt", "r") as f:
mydict = {} #create a dictionary called mydict
for line in f:
key, val = line.strip("\"\n[]").split(",")
mydict[key.strip("'")] = val.strip()
print(mydict) #test
for key in mydict:
print(key) #test to see if the keys are being retrieved correctly
readfiletodict()
Output:
(py35x64_test) c:\Work\Dev\StackOverflow\q46041167>python a.py
{'d': '0', 'c': '3', 'a': '5', 'b': '2'}
d
c
a
b
The efficient way to do this would be using python lists as suggested by #Tico.
However, if for some reason you can't, you can try this.
lineFormat = re.sub('[^A-Za-z0-9,]+', '', line)
this will transform "['a', 5]" to a,5. Now you can apply your split function.
(key,val) = lineFormat.split(",")
mydict[key]=val
It's much easier if you transform your string_list in a real python list, so you don't need parsing. Use json loads:
import json
...
list_line = json.loads(line)
...
Hope it helps!
You can use regex and a dict-comprehension to do that:
#!/usr/bin/env python
import re
with open('file.txt', 'r') as f: l = f.read().splitlines()
d = {''.join(re.findall('[a-zA-Z]+',i)):int(''.join(re.findall('\d',i))) for i in l}
Result:
{'a': 5, 'c': 3, 'b': 2, 'd': 0}
Using only a very basic knowledge of Python:
>>> mydict = {}
>>> with open('temp.txt') as the_input:
... for line in the_input:
... values = line.replace('"', '').replace("'", '').replace(',', '').replace('[', '').replace(']', '').rstrip().split(' ')
... mydict[values[0]] = int(values[1])
...
>>> mydict
{'a': 5, 'b': 2, 'c': 3, 'd': 0}
In other words, discard all of the punctuation, leaving only the blank between the two values needed for the dictionary. Split on that blank, then put the pieces from the split into the dictionary.
Edit: In a similar vein, using a regex. The re.sub looks for the various alternative characters given by its first argument and any that are found are replaced by its second argument, an empty string. The alternatives are delimited by the '|' character in a regex pattern. Some of the alternatives, such as the '[', must be escaped with an '\' because on their own they have special meanings within a regex expression.
>>> mydict = {}
>>> with open('temp.txt') as the_input:
... for line in the_input:
... values = re.sub(r'"|\'|\,|\[|\]|,', '', line).split(' ')
... mydict[values[0]] = int(values[1])
...
>>> mydict
{'a': 5, 'b': 2, 'c': 3, 'd': 0}
You were almost there, missing two things:
stripping the keys
converting the values
The following code does what you need (I think):
#!/usr/bin/env python
# -*- coding: utf-8 -*-
output = dict()
with open('input', 'r') as inputfile:
for line in inputfile:
line = line.strip('"[]\n')
key, val = line.split(',')
output[key.strip("'")] = int(val)
Be careful however, since this code is very brittle. It won't process any variations on the input format you have provided correctly. To build on top of this, I'd recommend to at least use except ValueError for the int conversion and to think about the stripping characters again.

How to print values from a file?

I have a text file and its content is something like this:
A:3
B:5
C:7
A:8
C:6
I need to print:
A numbers: 3, 8
B numbers: 5
C numbers: 7, 6
I'm a beginner so if you could give some help I would appreciate it. I have made a dictionary but that's pretty much all I know.
You could use an approach that keeps the values in a dictionary:
d = {} # create an empty dictionary
for line in open(filename): # opens the file
k, v = line.split(':') # unpack each line in the char before : and after
if k in d: # add the values to the dictionary
d[k].append(v)
else:
d[k] = [v]
This gives you a dictionary containing your file in a format that you can utilize to get the desired output:
for key, values in sorted(d.items()):
print(key, 'numbers:' ', '.join(values))
The sorted is required because dictionaries are unordered.
Note that using collections.defaultdict instead of a normal dict could simplify the approach somewhat. The:
d = {}
...
if k in d: # add the values to the dictionary
d[k].append(v)
else:
d[k] = [v]
could then be replaced by:
from collections import defaultdict
d = defaultdict(list)
...
d[k].append(v)
Short version (Which should sort in alphabetic order)
d = {}
lines = [line.rstrip('\n') for line in open('filename.txt')]
[d.setdefault(line[0], []).append(line[2]) for line in lines]
[print(key, 'numbers:', ', '.join(values)) for key,values in sorted(d.items())]
Or if you want to maintain the order as they appear in file (file order)
from collections import OrderedDict
d = OrderedDict() # Empty dict
lines = [line.rstrip('\n') for line in open('filename.txt')] # Get the lines
[d.setdefault(line[0], []).append(line[2]) for line in lines] # Add lines to dictionary
[print(key, 'numbers:', ', '.join(values)) for key,values in d.items()] # Print lines
Tested with Python 3.5.
You can treat your file as csv (comma separated value) so you can use the csv module to parse the file in one line. Then use defaultdict with input in the costructor the class list to say that to create it when the key not exists. Then use OrderedDict class because standard dictionary don't keeps the order of your keys.
import csv
from collection import defaultdict, OrderedDict
values = list(csv.reader(open('your_file_name'), delimiter=":")) #[['A', '3'], ['B', '5'], ['C', '7'], ['A', '8'], ['C', '6']]
dct_values = defaultdict(list)
for k, v in values:
dct_values[k].append(v)
dct_values = OrderedDict(sorted(dct_values.items()))
Then you can simply print iterating the dictionary.
A very easy way to group by key is by external library, if you are interested try PyFunctional

Converting this list into Dictionary using Python

list = ['Name=Sachin\n', 'country=India\n', 'game=cricket\n']
I want this list in a dictionary with keys as Name, country, game and values as Sachin, India, cricket as corresponding values. I got this list using readlines() from a text file.
>>> lst = ['Name=Sachin\n', 'country=India\n', 'game=cricket\n']
>>> result = dict(e.strip().split('=') for e in lst)
>>> print(result)
{'Name': 'Sachin', 'country': 'India', 'game': 'cricket'}
Just another way using regex.
>>> lis = ['Name=Sachin\n','country=India\n','game=cricket\n']
>>> dict(re.findall(r'(\w+)=(\w+)',''.join(lis)))
{'Name': 'Sachin', 'game': 'cricket', 'country': 'India'}
in one line:
lst =['Name=Sachin\n','country=India\n','game=cricket\n']
dct = dict( (item.split('=')[0], item.split('=')[1].strip()) for item in lst )
print(dct)
# {'game': 'cricket', 'country': 'India', 'Name': 'Sachin'}
note: list ist not a good variable name!
strip() is called twice which is not all that nice - this may be better:
def splt(item):
sp = item.strip().split('=')
return sp[0], sp[1]
dct = dict( splt(item) for item in lst )
print(dct)
The following should work:
my_list = ['Name=Sachin\n', 'country=India\n', 'game=cricket\n']
my_dict = {}
for entry in my_list:
key, value = entry.strip().split('=')
my_dict[key] = value
print my_dict
This give you the following dictionary:
{'country': 'India', 'game': 'cricket', 'Name': 'Sachin'}
Note, you should not use a variable name of list as this is used as a Python function.
If you are reading from a file, you could do this is follows:
with open('input.txt', 'r') as f_input:
my_dict = {}
for entry in f_input:
key, value = entry.strip().split('=')
my_dict[key] = value
print my_dict
answer = {}
with open('path/to/file') as infile:
for line in infile: # note: you don't need to call readlines()
key, value = line.split('=')
answer[key.strip()] = value.strip()
Use dictionary comprehension:
d = {
k: v
for k, v in map(
lambda x: x.strip().split('='),
yourlist
)
}
And as Peter Wood suggested rename your list variable not to shadow the built-in list.

Categories

Resources