Ik probeer een bestand te maken dat er als volgt uitziet
AAA x 111
AAB x 111
AAA x 112
AAC x 123
...
En gebruik een woordenboek zodat de output er als volgt uitziet
{AAA: ['111', '112'], AAB: ['111'], AAC: [123], ...}
Dit is wat ik'heb geprobeerd
file = open("filename.txt", "r")
readline = file.readline().rstrip()
while readline!= "":
list = []
list = readline.split(" ")
j = list.index("x")
k = list[0:j]
v = list[j + 1:]
d = {}
if k not in d == False:
d[k] = []
d[k].append(v)
readline = file.readline().rstrip()
Ik krijg steeds een TypeError: unhashable type: 'list'
. Ik weet dat sleutels in een woordenboek geen lijsten kunnen zijn, maar ik probeer van mijn waarde een lijst te maken en niet de sleutel. Ik'ben benieuwd of ik ergens een fout heb gemaakt.
Zoals aangegeven door de andere antwoorden, is de fout te wijten aan k = list[0:j]
, waar je sleutel is geconverteerd naar een lijst. Wat je zou kunnen proberen is je code te herwerken om gebruik te maken van de split
functie:
# Using with ensures that the file is properly closed when you're done
with open('filename.txt', 'rb') as f:
d = {}
# Here we use readlines() to split the file into a list where each element is a line
for line in f.readlines():
# Now we split the file on `x`, since the part before the x will be
# the key and the part after the value
line = line.split('x')
# Take the line parts and strip out the spaces, assigning them to the variables
# Once you get a bit more comfortable, this works as well:
# key, value = [x.strip() for x in line]
key = line[0].strip()
value = line[1].strip()
# Now we check if the dictionary contains the key; if so, append the new value,
# and if not, make a new list that contains the current value
# (For future reference, this is a great place for a defaultdict :)
if key in d:
d[key].append(value)
else:
d[key] = [value]
print d
# {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}
Merk op dat als je Python 3.x gebruikt, je'een kleine aanpassing zult moeten maken om het goed te laten werken. Als je het bestand opent met rb
, moet je line = line.split(b'x')
gebruiken (die ervoor zorgt dat je de byte splitst met het juiste type string). Je kunt het bestand ook openen met with open('filename.txt', 'rU') als f:
(of zelfs with open('filename.txt', 'r') als f:
) en het zou goed moeten werken.
Je probeert k
(wat een lijst is) te gebruiken als een sleutel voor d
. Lijsten zijn muteerbaar en kunnen niet als dict-sleutels worden gebruikt.
Ook initialiseer je nooit de lijsten in het woordenboek, vanwege deze regel:
if k not in d == False:
Wat zou moeten zijn:
if k not in d == True:
Wat eigenlijk zou moeten zijn:
if k not in d:
De TypeError
gebeurt omdat k
een lijst is, omdat het is gemaakt met behulp van een slice van een andere lijst met de regel k = list[0:j]
. Dit zou waarschijnlijk iets moeten zijn als k = ' '.join(list[0:j])
, zodat je in plaats daarvan een string hebt.
Bovendien is je if
statement niet correct, zoals opgemerkt door Jesse's antwoord, dat zou moeten luiden if k niet in d
of if niet k in d
(ik geef de voorkeur aan het laatste).
Je wist ook je woordenboek bij elke iteratie omdat je d = {}
binnen je for
lus hebt.
Merk op dat je ook list
of file
niet moet gebruiken als variabele namen, omdat je dan builtins maskeert.
Hier is hoe ik je code zou herschrijven:
d = {}
with open("filename.txt", "r") as input_file:
for line in input_file:
fields = line.split()
j = fields.index("x")
k = " ".join(fields[:j])
d.setdefault(k, []).append(" ".join(fields[j+1:]))
De dict.setdefault()
methode hierboven vervangt de if k not in d
logica uit je code.