Я'пытаюсь взять файл, который выглядит следующим образом ``none AAA x 111 AAB x 111 AAA x 112 AAC x 123 ...
И используйте словарь, чтобы вывод выглядел следующим образом
{AAA: ['111', '112'], AAB: ['111'], AAC: [123], ...}
Вот что я пробовал
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()
Я продолжаю получать `TypeError: unhashable type: 'list'`. Я знаю, что ключи в словаре не могут быть списками, но я пытаюсь сделать мое значение списком, а не ключом. Мне интересно, не допустил ли я где-то ошибку.
Как указано в других ответах, ошибка связана с k = list[0:j]
, где ваш ключ преобразуется в список. Вы можете попробовать переделать свой код, чтобы воспользоваться функцией split
:
# 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']}
Обратите внимание, что если вы используете Python 3.x, вам придется сделать небольшую поправку, чтобы заставить ее работать правильно. Если вы открываете файл с помощью rb
, вам'нужно использовать line = line.split(b'x')
(что позволяет убедиться, что вы разделяете байт с правильным типом строки). Вы также можете открыть файл, используя with open('filename.txt', 'rU') as f:
(или даже with open('filename.txt', 'r') as f:
), и он должен работать нормально.
Вы пытаетесь использовать k
(который является списком) в качестве ключа для d
. Списки являются изменяемыми и не могут использоваться в качестве ключей dict.
Кроме того, из-за этой строки вы никогда не инициализируете списки в словаре:
if k not in d == False:
Что должно быть:
if k not in d == True:
Что на самом деле должно быть:
if k not in d:
<б>Примечание:</б> Этот ответ явно не ответ на заданный вопрос. других ответов у него. Так как вопрос специфический сценарию и подна исключение-общие, этот ответ указывает на общий случай.
Хэш-значения только целых чисел, которые используются для сравнения ключей словарь во время просмотра словаря, быстро.
Внутренне, хэш()вызов метода
хэша () метод объекта, который устанавливается по умолчанию для любого объекта.
>>> a = [1,2,3,4,[5,6,7],8,9]
>>> set(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
Это происходит из-за списка в список, который является списком, который не может быть хэширован. Которая может быть решена путем преобразование внутренней вложенные списки кортеж,
>>> set([1, 2, 3, 4, (5, 6, 7), 8, 9])
set([1, 2, 3, 4, 8, 9, (5, 6, 7)])
>>> hash([1, 2, 3, [4, 5,], 6, 7])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> hash(tuple([1, 2, 3, [4, 5,], 6, 7]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> hash(tuple([1, 2, 3, tuple([4, 5,]), 6, 7]))
-7943504827826258506
решение, чтобы избежать этой ошибки-это перестроить список, чтобы иметь вложенные кортежи вместо списков.
Причина вы'вновь, как unhashable типа: 'список'
исключение, потому что к = Список[0:Дж]наборы
K, чтобы быть "на срез" из списка, который логически другой, чаще более короткий, список. Что вам нужно, чтобы получить только первый элемент в списке, написано так как к = Список[0]
. То же самое Для в = список[Дж + 1:], которая должна быть в = список[2]
Третий элемент списка, возвращаемого от звонка с readline.сплит (назальный;)
.
Я заметил несколько других вероятных проблем с кодом, которые я'МР упомянуть несколько. На самом деле это вы Дон'т хотите, чтобы (пере)инициализации Д
С Д = {}
для каждой строки читать в цикле. Еще это'ы вообще не очень хорошая идея называть переменные так же, как любой из встроенных типов, так как это'МР помешать вам быть в состоянии получить доступ к одной из них, если вам это нужно — и это'ы путаете с другими, которые используются для имен, обозначающих один из стандартных элементов. По этой причине, вы должны переименовать переменную переменная список
что-то другое, чтобы избежать подобные проблемы.
Здесь'ы рабочая версия с этими изменениями в нем, я также упростил если
заявление, выражения у вас, который проверяет, чтобы увидеть, если ключ уже есть в словаре — есть еще короче неявных способов сделать такого рода вещи, но, используя условный оператор-это нормально.
d = {}
file = open("filename.txt", "r")
readline = file.readline().rstrip()
while readline:
lst = readline.split(" ") # Split into sequence like ['AAA', 'x', '111'].
k = lst[0] # First item.
v = lst[2] # Third item.
if k not in d: # New key?
d[k] = [] # Initialize its associated value to an empty list.
d[k].append(v)
readline = file.readline().rstrip()
file.close() # Done reading file.
print('d: {}'.format(d))
Выход:
в
d: {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}
Ошибка TypeError
происходит потому, что k
является списком, поскольку он создается с помощью фрагмента другого списка со строкой k = list[0:j]
. Вероятно, это должно быть что-то вроде k = ' '.join(list[0:j])
, так что вместо этого у вас будет строка.
В дополнение к этому, ваше утверждение if
некорректно, как было отмечено в ответе Jesse's, которое следует читать if k not in d
или if not k in d
(я предпочитаю последнее).
Вы также очищаете свой словарь на каждой итерации, поскольку у вас есть d = {}
внутри цикла for
.
Обратите внимание, что вам также не следует использовать list
или file
в качестве имен переменных, поскольку вы будете маскировать встроенные модули.
Вот как я бы переписал ваш код:
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:]))
Приведенный выше метод dict.setdefault()
заменяет логику if k not in d
из вашего кода.