Python : TypeError : 해시 할 수없는 유형 : 'list'
다음과 같은 파일을 가져 오려고합니다.
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
. 목록은 변경 가능하며 사전 키로 사용할 수 없습니다.
또한 다음 줄 때문에 사전에 목록을 초기화하지 않습니다.
if k not in d == False:
다음 중 하나 여야합니다.
if k not in d == True:
실제로는 다음과 같습니다.
if k not in d:
참고 : 이 답변은 질문에 명시 적으로 답변하지 않습니다. 다른 답변은 그것을합니다. 질문은 시나리오 와 관련이 있고 발생한 예외는 general 이므로이 답변은 일반적인 경우를 가리 킵니다.
해시 값은 사전 조회 중에 사전 키를 빠르게 비교하는 데 사용되는 정수일뿐입니다.
내부적으로 hash()
메서드는 __hash__()
모든 개체에 대해 기본적으로 설정된 개체의 메서드를 호출 합니다.
중첩 된 목록을 집합으로 변환
>>> 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
The solution to avoid this error is to restructure the list to have nested tuples instead of lists.
The reason you're getting the unhashable type: 'list'
exception is because k = list[0:j]
sets k
to be a "slice" of the list, which is logically another, often shorter, list. What you need is to get just the first item in list, written like so k = list[0]
. The same for v = list[j + 1:]
which should just be v = list[2]
for the third element of the list returned from the call to readline.split(" ")
.
I noticed several other likely problems with the code, of which I'll mention a few. A big one is you don't want to (re)initialize d
with d = {}
for each line read in the loop. Another is it's generally not a good idea to name variables the same as any of the built-ins types because it'll prevent you from being able to access one of them if you need it — and it's confusing to others who are used to the names designating one of these standard items. For that reason, you ought to rename your variable list
variable something different to avoid issues like that.
Here's a working version of your with these changes in it, I also simplified the if
statement expression you had which checks to see if the key is already in the dictionary — there are even shorter implicit ways to do this sort of thing, but using a conditional statement is fine for now.
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))
Output:
d: {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}
The TypeError
is happening because k
is a list, since it is created using a slice from another list with the line k = list[0:j]
. This should probably be something like k = ' '.join(list[0:j])
, so you have a string instead.
In addition to this, your if
statement is incorrect as noted by Jesse's answer, which should read if k not in d
or if not k in d
(I prefer the latter).
You are also clearing your dictionary on each iteration since you have d = {}
inside of your for
loop.
Note that you should also not be using list
or file
as variable names, since you will be masking builtins.
Here is how I would rewrite your code:
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:]))
The dict.setdefault()
method above replaces the if k not in d
logic from your code.
python 3.2
with open("d://test.txt") as f:
k=(((i.split("\n"))[0].rstrip()).split() for i in f.readlines())
d={}
for i,_,v in k:
d.setdefault(i,[]).append(v)
참고URL : https://stackoverflow.com/questions/13675296/python-typeerror-unhashable-type-list
'Nice programing' 카테고리의 다른 글
종속성 주입 및 명명 된 로거 (0) | 2020.10.27 |
---|---|
Git이 파일을 바이너리 또는 텍스트로 처리하는지 확인하는 방법은 무엇입니까? (0) | 2020.10.27 |
UUID 형식 : 8-4-4-4-12-왜? (0) | 2020.10.27 |
iPhone에 구성 프로파일 설치-프로그래밍 방식 (0) | 2020.10.27 |
iPhone : WWDR 중간 인증서 란 무엇입니까? (0) | 2020.10.27 |