Python: TypeError: 해시할 수 없는 유형: &39;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()

유형 오류 : 해시 할 수없는 유형 : ' 목록'이 계속 발생합니다. 사전의 키는 목록이 될 수 없다는 것을 알고 있지만 내 값을 키가 아닌 목록으로 만들려고합니다. 제가 어딘가에서 실수를 한 것인지 궁금합니다.

해결책

다른 답변에서 알 수 있듯이 오류는 키가 목록으로 변환되는 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')를 f:로 사용하여 파일을 열 수도 있습니다(또는with open('filename.txt', 'r')를 f:`로 사용해도 정상적으로 작동합니다).

해설 (3)

목록인 kd의 키로 사용하려고 합니다. 목록은 변경 가능하므로 딕셔너리 키로 사용할 수 없습니다.

또한 이 줄 때문에 사전에서 목록을 초기화하지 않습니다:

if k not in d == False:

그래야 합니다:

if k not in d == True:

실제로는 그래야 합니다:

if k not in d:
해설 (1)

;;; Note:&lt &lt b&gt /b&gt. 이 질문에 답해야 질문과대답 질문이예요 명시적으로 않습니다. 다른 답변을 해. 문제는 특정 및 이후 책정안 뚜르산을 이 질문에 대한 예외는 일반 , 일반적인 경우 가리킵니다.

단지 비교할 때 사용되는 해시 값을 정수로 사전 키를 사전 검색 중에 있습니다.

내부적으로 '해시라고 객체의 방법 ()' 메서드 호출 () '' hash 기본적으로 설정된 객체에 대한.

  • * 네스트된 list 를 설정되었습니다 변환

>>> a = [1,2,3,4,[5,6,7],8,9]
>>> set(a)
Traceback (most recent call last):
  File "", line 1, in 
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 "", line 1, in 
TypeError: unhashable type: 'list'

>>> hash(tuple([1, 2, 3, [4, 5,], 6, 7]))
Traceback (most recent call last):
  File "", line 1, in 
TypeError: unhashable type: 'list'

>>> hash(tuple([1, 2, 3, tuple([4, 5,]), 6, 7]))
-7943504827826258506
  • 솔루션, 이를 방지하기 위해 &gt 오류: 구조조정을 위한 목록을 중첩할 튜플을 lists.* 대신
해설 (1)

그 이유는 you& # 39, re 가져오는 '오언사이블 유형: # 39, & # 39 list& ',' k = 목록 [0 j] '세트' k '예외는 될 수 있기 때문에 &quot slice"; 이는 종종 논리적으로 목록의 다른 짧고, 목록. What you need is afaq 그냥 먼저 목록의 항목, 그래서 '같은 기록되었으므로 k = 목록 [0]'. 같은 목록 "에 대한 v = [j + 1:] '할 수 있는' v = [2] 방금 목록 (call to '에서' 세 번째 요소에 대한 목록 반환되었습니다 예들린드스플리트 (&quot. ") '.

기타 여러 가지 문제가 될 건 물론 코드, 재배케하여 I& # 39, ll 언급하십시오 얼마 되지 않습니다. # 39 한 don& 큰 경우, (재) '을 (를) = {} 영업사원이에요 영업사원이에요 초기화하지 싶지 않다' 는 각 행은 읽어들입니다 루프지 # 39 의 또 다른 이유는 it& 일반적으로 내장 기능 같은 것은 좋은 방법이 com/go/4e6b330a_kr 이름 중 하나로, ll 없습니다 # 39 추상형데이터타입 같도다라고 it& 액세스하려면 있어야 한다는 그 중 하나가 필요할 때 리스토어와 it& # 39 의 혼동을 줄 사람도 이름이 사용되는 표준 중 하나를 지정 할 수 있습니다. 이러한 이유로, 당신이 할 일이 그렇게 문제를 방지하기 위해 뭔가 다른 게 변수 이름을 '변수' 목록.

39 의 here& 작업 버전에 대해 "만약 이런 변화를 통해 정보기술 (it), 난 또 '기술서임을 표현식에서는 여부를 확인하기 위해 사전에 확인하는 키는 이미 했습니다 - 짧은 가지 방법으로 구성할 수 있지만, 이러한 종류의 일을 해도 암시적입니다 사용하여 조건문을 정상입니다 됐다.

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))

출력:

<! - 언어: &gt 랑 없음 -;

d: {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}
해설 (0)

kk = list[0:j]줄이 있는 다른 목록의 슬라이스를 사용하여 생성되었기 때문에TypeError가 발생하고 있습니다. 이것은 아마도k = ' '.join(list[0:j])`와 같아야 하므로 대신 문자열이 있어야 합니다.

이 외에도 Jesse의 답변에서 언급했듯이 if 문은 if k가 d에 있지 않으면 또는 if k가 d에 있지 않으면(저는 후자를 선호합니다)으로 읽어야 하는 잘못된 문입니다.

또한 for 루프 안에 d = {}가 있기 때문에 각 반복마다 사전을 지우고 있습니다.

또한 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가 d에 있지 않은 경우 로직을 대체합니다.

해설 (3)
    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)
해설 (0)