Nice programing

Python : TypeError : 해시 할 수없는 유형 : 'list'

nicepro 2020. 10. 27. 23:27
반응형

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

반응형