Create Dict from Text File + Python:TypeError: 'str' object does not support item assignment - python

Trying to create a dict from this piece of text:
game_name: Adventure 1
game_goal: Find the magic helmet and bring it to Hans.
game_goalloc: 8
game_goalobj: helmet
game_start: 4
game_xsize: 3
game_ysize: 3
Read in as "config.txt", keep getting a Type Error: 'str' object does not support item assignment.
Can't for the life of me figure out why as doing the exact same operation elsewhere in my code... HELLLP
with open('config.txt') as f:
lines = f.readlines()
for line in lines:
line = line.strip()
if "game_" in line:
game = line.split('_')[-1]
k = game.split(':')[0]
v = game.split(':')[-1]
print(k)
print(v)
game[k] = {}
game[k] = v

created a empty dictionary game_dict = {} and updated it.
with open('game1.txt') as f:
lines = f.readlines()
game_dict = {}
for line in lines:
line = line.strip()
if "game_" in line:
game = line.split('_')[-1]
k = game.split(':')[0]
game_dict[k] = ""
v = game.split(':')[-1]
game_dict[k] = v
print(game_dict)
Output
{'name': ' Adventure 1', 'goal': ' Find the magic helmet and bring it to Hans.', 'goalloc': ' 8', 'goalobj': ' helmet', 'start': ' 4', 'xsize': ' 3', 'ysize': ' 3'}

game = line.split('_')[-1]
k = game.split(':')[0]
v = game.split(':')[-1]
print(k)
print(v)
game[k] = {}
game[k] = v
in the last two lines of codes, you are trying to assign the "game", a str object, with empty {} and then v. this results in the error.

lines = """
game_name: Adventure 1
game_goal: Find the magic helmet and bring it to Hans.
game_goalloc: 8
game_goalobj: helmet
game_start: 4
game_xsize: 3
game_ysize: 3
""".strip().splitlines()
game_dict = {}
for line in lines:
line = line.strip()
if "game_" in line:
game = line.split('_')[-1]
k = game.split(':')[0].strip()
v = game.split(':')[-1].strip()
print(k)
print(v)
game_dict[k] = {}
game_dict[k] = v
print(game_dict)
Maybe this is what you want.

Thanks! Yes - I figured that out just after posting.
I was initializing the dict variable as game and then using the same var within the loop. Silly mistake...
Here is my fixed code:
game = {}
map = {}
#need to update location variable here when a move is made
character = {'inventory': [], 'location': 1}
with open('game1.txt') as f:
lines = f.readlines()
for line in lines:
line = line.strip()
if "game_" in line:
split = line.split('_')[-1]
k,v = split.split(':')
game[k] = v

Related

Create variables from text file in Python

This is linked to this question here I used the first answer, I tried changing the code but it didn't seem to work as that example has "[]" in the variables
I have a text file here:
room1North = CP
room1East = CP
room1South = OP
room1West = OP
room2North = OP
room2East = CP
room2South = EP
room2West = OP
I would like Python to create variables with the values in the text file so the variable "room1North = CP" in Python
I have the following code so far
with open("maze files.txt", "r") as f:
data = f.readlines()
room1North, room1East, room1South, room1West, room2North, room2Eeast, room2South, room2West = [d.split('=')[1].split('\n')[0] for d in data]
I get the following error:
IndexError: list index out of range
You don't actually want separate variables; you want a single dict whose keys are read from the file.
with open("maze files.txt", "r") as f:
data = {k:v for k, v in [line.strip().replace(' ', '').split("=") for line in f]}
# data["room1North"] == "CP"
# data["room1East"] == "CP"
# data["room1South"] == "OP"
# etc
Change your code as bellow
with open("maze files.txt", "r") as f:
data = f.readlines()
room1North, room1East, room1South, room1West, room2North, room2Eeast, room2South, room2West = [d.split('=')[1].split('\n')[0] for d in ''.join(data).split('\n')]
I think you'd have more luck using a dictionary rather than relying on pure variables.
with open("maze files.txt", "r") as f:
data = f.readlines()
rooms = {}
for i in data:
currentRoom = i.replace(' ', '').strip().split('=')
rooms[currentRoom[0]] = currentRoom[1]
What you'll be left with is a dictionary like the following
print(rooms)
#{'room1North ': ' CP', 'room1East ': ' CP', 'room1South ': ' OP', 'room1West ': ' OP', 'room2North ': ' OP', 'room2East ': ' CP', 'room2South ': ' EP', 'room2 West ': ' OP'}
You can reference each room and it's value by rooms["room1North"]

Error in code wont allow me to progress

I get an error when i run this code
cost = float(prices[strs[0]][0])
TypeError: float() argument must be a string or a number, not 'list'
i dont know how to fix the error
prices = {}
groceries = []
file = open("grocery_store_price_list.txt", "r")
for strx in file:
strs = list(filter(None, strx.strip().split(" ")))
prices[strs[0]] = [strs[1]], [strs[2]]
file.close()
file = open("my_personal_gro_list.txt", "r")
for strx in file :
strs = list(filter(None, strx.strip().split(" ")))
groceries.append([strs[1], strs[0]])
headings = "{:15s} {:3s} {:10s} {:5s} {:6s}".format("item", "qty", "unit",
"cost", "total")
print(headings)
finalCost = 0
for strs in groceries
item = strs[0]
qty = int(strs[1])
unit = prices[strs[0]][1]
cost = float(prices[strs[0]][0])
prices[strs[0]][0] is a list that contains two prices. So you'll want to cast both values separately or using cost = [float(v) for v in prices[strs[0]][0]].
prices = {}
groceries = []
file = open("grocery_store_price_list.txt", "r")
for strx in file:
strs = list(filter(None, strx.strip().split(" ")))
prices[strs[0]] = [strs[1]], [strs[2]] # List of two prices, why you get the error.
file.close()
file = open("my_personal_gro_list.txt", "r")
for strx in file :
strs = list(filter(None, strx.strip().split(" ")))
groceries.append([strs[1], strs[0]])
headings = "{:15s} {:3s} {:10s} {:5s} {:6s}".format("item", "qty", "unit",
"cost", "total")
print(headings)
finalCost = 0
for strs in groceries
item = strs[0]
qty = int(strs[1])
unit = prices[strs[0]][1]
cost = [float(v) for v in prices[strs[0]][0]]
# OR cost = [float(prices[strs[0]][0][0]), float(prices[strs[0]][0][1])]
>>> prices = {}
>>> prices['a'] = [1], [2]
>>> prices
{'a': ([1], [2])}
Taking above as an example, your prices contains a tuple and each is a list that contains 1 element
prices[strs[0]] = [strs[1]], [strs[2]]
You either apply float() on one of the values or modify your prices let each key has one value

how to read a specific line which starts in "#" from file in python

how can i read a specific line which starts in "#" from file in python and
set that line as a key in a dictionary (without the "#") and set all the lines after that line until the next "#" as a value is the dictionary
please help me
here is the file :
from collections import defaultdict
key = 'NOKEY'
d = defaultdict(list)
with open('thefile.txt', 'r') as f:
for line in f:
if line.startswith('#'):
key = line.replace('#', '')
continue
d[key].append(line)
Your dictionary will have a list of lines under each key. All lines that come before the first line starting with '#' would be stored under the key 'NOKEY'.
You could make use of Python's groupby function as follows:
from itertools import groupby
d = {}
key = ''
with open('input.txt', 'r') as f_input:
for k, g in groupby(f_input, key=lambda x: x[0] == '#'):
if k:
key = next(g).strip(' #\n')
else:
d[key] = ''.join(g)
print d
This would give you the following kind of output:
{'The Piper at the gates of dawn': '*Lucifer sam....\nsksdlkdfslkj\ndkdkfjoiupoeri\nlkdsjforinewonre\n', 'A Saucerful of Secrets': '*Let there be\nPeople heard him say'}
Tested using Python 2.7.9
A pretty simple version
filename = 'test'
results = {}
with open(filename, 'r') as f:
while (1):
text = f.readline()
if (text == ''):
break
elif (text[0] == "#"):
key = text
results[key] = ''
else:
results[key] += text
From (ignoring additional blank lines, a bi-product of the Answer formatting):
#The Piper at the gates of dawn
*Lucifer sam....
sksdlkdfslkj
dkdkfjoiupoeri
lkdsjforinewonre
# A Saucerful of Secrets
*Let there be
People heard him say
Produces:
{'#The Piper at the gates of dawn\n': '*Lucifer sam....\nsksdlkdfslkj\ndkdkfjoiupoeri\nlkdsjforinewonre\n', '# A Saucerful of Secrets \n': '*Let there be\nPeople heard him say\n'}

Save dictionary to file

I have a file looking like this:
732772 scaffold-3 G G A
732772 scaffold-2 G G A
742825 scaffold-3 A A G
776546 scaffold-3 G A G
776546 scaffold-6 G A G
I'm interested in using column 2 as my key, and output in a way that: having a unique key, and assiociated with it values.
in other words, if name in column 2 occurs more than once, output it only once, therefore the output should be:
scaffold-3
732772 G G A
742825 A A G
776546 G A G
scaffold-2
732772 G G A
scaffold-6
776546 G A G
I wrote sth like this:
res = open('00test','r')
out = open('00testresult','w')
d = {}
for line in res:
if not line.startswith('#'):
line = line.strip().split()
pos = line[0]
name = line[1]
call = line[2]
father = line[3]
mother = line[4]
if not (name in d):
d[name] = []
d[name].append({'pos':pos,'call':call,'father':father,'mother':mother})
but I have no idea, how to output it in a way I described above.
Any help will be nice
EDIT:
This is fully working code, that solved the problem:
res = open('00test','r')
out = open('00testresult','w')
d = {}
for line in res:
if not line.startswith('#'):
line = line.strip().split()
pos = line[0]
name = line[1]
call = line[2]
father = line[3]
mother = line[4]
if not (name in d):
d[name] = []
d[name].append({'pos':pos,'call':call,'father':father,'mother':mother})
for k,v in d.items():
out.write(str(k)+'\n')
for i in v:
out.write(str(i['pos'])+'\t'+str(i['call'])+'\t'+str(i['father'])+'\t'+str(i['mother'])+'\n')
out.close()
Now that you have your dictionary, loop over the items and write to a file:
keys = ('pos', 'call', 'father', 'mother')
with open(outputfilename, 'w') as output:
for name in d:
output.write(name + '\n')
for entry in d['name']:
output.write(' '.join([entry[k] for k in keys]) + '\n')
You may want to use a collections.defaultdict() object instead of a regular dictionary for d:
from collections import defaultdict
d = defaultdict(list)
and remove the if not (name in d): d[name] = [] lines altogether.

Group and Check-mark using Python

I have several files, each of which has data like this (filename:data inside separated by newline):
Mike: Plane\nCar
Paula: Plane\nTrain\nBoat\nCar
Bill: Boat\nTrain
Scott: Car
How can I create a csv file using python that groups all the different vehicles and then puts a X on the applicable person, like:
Assuming those line numbers aren't in there (easy enough to fix if they are), and with an input file like following:
Mike: Plane
Car
Paula: Plane
Train
Boat
Car
Bill: Boat
Train
Scott: Car
Solution can be found here : https://gist.github.com/999481
import sys
from collections import defaultdict
import csv
# see http://stackoverflow.com/questions/6180609/group-and-check-mark-using-python
def main():
# files = ["group.txt"]
files = sys.argv[1:]
if len(files) < 1:
print "usage: ./python_checkmark.py file1 [file2 ... filen]"
name_map = defaultdict(set)
for f in files:
file_handle = open(f, "r")
process_file(file_handle, name_map)
file_handle.close()
print_csv(sys.stdout, name_map)
def process_file(input_file, name_map):
cur_name = ""
for line in input_file:
if ":" in line:
cur_name, item = [x.strip() for x in line.split(":")]
else:
item = line.strip()
name_map[cur_name].add(item)
def print_csv(output_file, name_map):
names = name_map.keys()
items = set([])
for item_set in name_map.values():
items = items.union(item_set)
writer = csv.writer(output_file, quoting=csv.QUOTE_MINIMAL)
writer.writerow( [""] + names )
for item in sorted(items):
row_contents = map(lambda name:"X" if item in name_map[name] else "", names)
row = [item] + row_contents
writer.writerow( row )
if __name__ == '__main__':
main()
Output:
,Mike,Bill,Scott,Paula
Boat,,X,,X
Car,X,,X,X
Plane,X,,,X
Train,,X,,X
Only thing this script doesn't do is keep the columns in order that the names are in. Could keep a separate list maintaining the order, since maps/dicts are inherently unordered.
Here is an example of how-to parse these kind of files.
Note that the dictionary is unordered here. You can use ordered dict (in case of Python 3.2 / 2.7) from standard library, find any available implmentation / backport in case if you have older Python versions or just save an order in additional list :)
data = {}
name = None
with open(file_path) as f:
for line in f:
if ':' in line: # we have a name here
name, first_vehicle = line.split(':')
data[name] = set([first_vehicle, ]) # a set of vehicles per name
else:
if name:
data[name].add(line)
# now a dictionary with names/vehicles is available
# let's convert it to simple csv-formatted string..
# a set of all available vehicles
vehicles = set(v for vlist in data.values()
for v in vlist)
for name in data:
name_vehicles = data[name]
csv_vehicles = ''
for v in vehicles:
if v in name_vehicles:
csv_vehicles += v
csv_vehicles += ','
csv_line = name + ',' + csv_vehicles
Assuming that the input looks like this:
Mike: Plane
Car
Paula: Plane
Train
Boat
Car
Bill: Boat
Train
Scott: Car
This python script, places the vehicles in a dictionary, indexed by the person:
#!/usr/bin/python
persons={}
vehicles=set()
with open('input') as fd:
for line in fd:
line = line.strip()
if ':' in line:
tmp = line.split(':')
p = tmp[0].strip()
v = tmp[1].strip()
persons[p]=[v]
vehicles.add(v)
else:
persons[p].append(line)
vehicles.add(line)
for k,v in persons.iteritems():
print k,v
print 'vehicles', vehicles
Result:
Mike ['Plane', 'Car']
Bill ['Boat', 'Train']
Scott ['Car']
Paula ['Plane', 'Train', 'Boat', 'Car']
vehicles set(['Train', 'Car', 'Plane', 'Boat'])
Now, all the data needed are placed in data-structures. The csv-part is left as an exercise for the reader :-)
The most elegant and simple way would be like so:
vehiclesToPeople = {}
people = []
for root,dirs,files in os.walk('/path/to/folder/with/files'):
for file in files:
person = file
people += [person]
path = os.path.join(root, file)
with open(path) as f:
for vehicle in f:
vehiclesToPeople.setdefault(vehicle,set()).add(person)
people.sort()
table = [ ['']+people ]
for vehicle,owners in peopleToVehicles.items():
table.append([('X' if p in vehiclesToPeople[vehicle] else '') for p in people])
csv = '\n'.join(','.join(row) for row in table)
You can do pprint.pprint(table) as well to look at it.

Categories