अजगर: टाइपरोर: अस्वाभाविक प्रकार: 'सूची'


94

मैं एक फाइल लेने की कोशिश कर रहा हूं जो इस तरह दिखती है

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'। मुझे पता है कि एक शब्दकोश में कुंजियाँ सूचीबद्ध नहीं की जा सकती हैं, लेकिन मैं एक सूची में अपना मूल्य बनाने की कोशिश कर रहा हूं, कुंजी नहीं। मैं सोच रहा हूं कि क्या मैंने कहीं गलती की है।

जवाबों:


56

जैसा कि अन्य उत्तरों से संकेत मिलता है, त्रुटि के कारण है 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']}

ध्यान दें कि यदि आप पायथन 3.x का उपयोग कर रहे हैं, तो आपको इसे ठीक से काम करने के लिए एक मामूली समायोजन करना होगा। यदि आप फ़ाइल को खोलते हैं rb, तो आपको उपयोग करना होगा line = line.split(b'x')(जो यह सुनिश्चित करता है कि आप उचित प्रकार के स्ट्रिंग के साथ बाइट को विभाजित कर रहे हैं)। आप फ़ाइल का उपयोग करके भी खोल सकते हैं with open('filename.txt', 'rU') as f:(या यहां तक ​​कि with open('filename.txt', 'r') as f:) और इसे ठीक काम करना चाहिए।


मैंने यह कोशिश की और मुझे टाइपर्रर मिलता है: टाइप स्ट्रिंग लाइन "लाइन = लाइन.प्लिट ('x')" पर बफर एपीआई का समर्थन नहीं करता है
कीनन

1
@ user1871081 आह, क्या आप पायथन 3.x का उपयोग कर रहे हैं? मैं एक अद्यतन पोस्ट करूँगा जो इसके साथ काम करे।
राकेटडॉन्की

31

नोट: यह उत्तर स्पष्ट रूप से पूछे गए प्रश्न का उत्तर नहीं देता है। अन्य उत्तर यह करते हैं। चूंकि प्रश्न एक परिदृश्य के लिए विशिष्ट है और उठाया अपवाद सामान्य है , यह उत्तर सामान्य मामले की ओर इशारा करता है।

हैश मान केवल पूर्णांक हैं, जिनका उपयोग शब्दकोश कुंजियों को शब्दकोष की तुलना में जल्दी देखने के लिए किया जाता है।

आंतरिक रूप से, 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

इस त्रुटि से बचने का उपाय सूचियों के बजाय नेस्टेड टुपल्स की सूची का पुनर्गठन करना है।


4
क्या होगा अगर सूची बहुत बड़ी है ?? ऐसा लगता है कि एक अच्छा समाधान है, लेकिन सामान्य रूप से पर्याप्त नहीं है
msh855

1
@ msh855 क्या कोई आकार सीमा है? मैंने शब्दकोश का आकार 100,000 के एक टपल के साथ परीक्षण किया और यह मेरे लिए ठीक काम किया (मैं अजगर 3.6 का उपयोग कर रहा हूं)
श्रीराम

18

आप kएक कुंजी के रूप में (जो एक सूची है) का उपयोग करने की कोशिश कर रहे हैं d। सूचियाँ परिवर्तनशील हैं और इन्हें तानाशाही कुंजी के रूप में उपयोग नहीं किया जा सकता है।

इस पंक्ति के कारण, आप कभी भी सूचियों को सूची में शामिल नहीं कर रहे हैं:

if k not in d == False:

जो होना चाहिए:

if k not in d == True:

जो वास्तव में होना चाहिए:

if k not in d:

5

आपके द्वारा unhashable type: 'list'अपवाद प्राप्त करने का कारण यह है क्योंकि सूची का "टुकड़ा" होना k = list[0:j]सेट kहै, जो तार्किक रूप से एक और, अक्सर छोटा, सूची है। लिस्ट में सिर्फ पहला आइटम पाने के लिए आपको क्या चाहिए, ऐसा लिखा है k = list[0]। वही v = list[j + 1:]जिसके v = list[2]लिए कॉल से लौटे सूची के तीसरे तत्व के लिए होना चाहिए readline.split(" ")

मैंने कोड के साथ कई अन्य संभावित समस्याओं पर ध्यान दिया, जिनमें से कुछ का उल्लेख करूंगा। एक बड़ा वह है जिसे आप लूप में पढ़ी गई प्रत्येक पंक्ति के dसाथ आरंभ (पुनः) नहीं करना चाहते हैं d = {}। एक और यह आम तौर पर किसी भी निर्मित-इन प्रकार के चर को नाम देने के लिए एक अच्छा विचार नहीं है क्योंकि यह आपको ज़रूरत पड़ने पर उनमें से एक का उपयोग करने से रोक देगा - और यह उन लोगों को भ्रमित कर रहा है जो उपयोग किए जाते हैं इन मानक वस्तुओं में से एक को नामित करने वाले नाम। इस कारण से, आपको इस listतरह के मुद्दों से बचने के लिए अपने चर चर का नाम बदलना चाहिए ।

इसमें इन परिवर्तनों के साथ आपका एक कार्यशील संस्करण है, मैंने आपके द्वारा ifदिए गए कथन की अभिव्यक्ति को भी सरल बनाया है, जिसमें यह देखा गया है कि क्या कुंजी पहले से ही शब्दकोश में है - इस तरह के काम करने के लिए और भी छोटे निहितार्थ हैं, लेकिन सशर्त का उपयोग करना बयान अभी के लिए ठीक है

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']}

0

ऐसा TypeErrorइसलिए हो रहा है क्योंकि kएक सूची है, क्योंकि यह रेखा के साथ किसी अन्य सूची से एक स्लाइस का उपयोग करके बनाई गई है k = list[0:j]। यह शायद कुछ ऐसा होना चाहिए k = ' '.join(list[0:j]), इसलिए आपके पास एक स्ट्रिंग है।

इसके अतिरिक्त, आपका ifकथन गलत है जैसा कि जेसी के उत्तर द्वारा नोट किया गया है, जिसे पढ़ना चाहिए 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आपके कोड से तर्क को बदल देती है ।


जबकि वरीयता आपका पूरा अधिकार है, not k in dएक नौसिखिया के रूप में भ्रमित कर सकता है (not k) in d, जबकि k not in dकोई अस्पष्टता नहीं है
जेसी द गेम

मैं यह भी तर्क दूंगा कि यह 'पाइथोनिक' तरीका not inहै जिसे एक ऑपरेटर के रूप में सूचीबद्ध किया गया है ।
जेसी द गेम

हाँ, मुझे लगता है कि मेरी प्राथमिकता शायद अन्य भाषाओं को सीखने से है, जहाँ एक परिक्षण परीक्षा जैसी चीज़ के लिए आपके पास ऑपरेटर नहीं होंगे, इसलिए आप कुछ ऐसा करेंगे !a.contains(b)not inअधिक पाइथोनिक हो सकता है, मैं सिर्फ दो शब्द ऑपरेटरों की अवधारणा को बूलियन अभिव्यक्ति पर एक व्युत्क्रम का उपयोग करने से अधिक भ्रमित करता हूं।
एंड्रयू क्लार्क

-1
    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)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.