2012-12-02 29 views
32

मैं एक फ़ाइल है कि इसपायथन: लेखन त्रुटि: unhashable प्रकार: 'सूची'

AAA x 111 
AAB x 111 
AAA x 112 
AAC x 123 
... 

तरह लग रहा है और एक शब्दकोश का उपयोग करने के लिए इतना है कि उत्पादन इस

{AAA: ['111', '112'], AAB: ['111'], AAC: [123], ...} 
तरह लग रहा है करने के लिए कोशिश कर रहा हूँ unhashable प्रकार:: 'सूची'

यह मैं

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

मैं एक लेखन त्रुटि मिलती रहती है क्या कोशिश की है है। मुझे पता है कि एक शब्दकोश में कुंजी सूचियां नहीं हो सकती हैं, लेकिन मैं अपनी मान को सूची में बनाने की कोशिश नहीं कर रहा हूं। मैं सोच रहा हूं कि मैंने कहीं गलती की है।

उन सभी के लिए धन्यवाद जिन्होंने मुझे अपने अंतिम प्रश्न के साथ मदद की।

उत्तर

20

जैसा कि अन्य उत्तरों से संकेत मिलता है, त्रुटि 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:) का उपयोग करके फ़ाइल भी खोल सकते हैं और इसे ठीक काम करना चाहिए।

+0

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

+0

@ user1871081 आह, क्या आप पाइथन 3.x का उपयोग कर रहे हैं? मैं एक अद्यतन पोस्ट करूंगा जो उसके साथ काम करना चाहिए। – RocketDonkey

+1

@ user1871081 बहुत बढ़िया, सबकुछ के साथ शुभकामनाएं। – RocketDonkey

10

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

इसके अलावा, आप कभी नहीं सूचियों शब्दकोश में इस लाइन की वजह से आरंभ कर रहे हैं,:

if k not in d == False: 

कौन होना चाहिए:

if k not in d == True: 

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

if k not in d: 
+0

परिवर्तन के साथ यहां तक ​​कि यह अभी भी एक ही त्रुटि देता है। – Keenan

0

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

इस के अलावा, अपने if बयान के रूप में जेसी का जवाब है, जो पढ़ना चाहिए if k not in d या if not k in 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 not in d तर्क की जगह:

यहाँ कैसे मैं अपने कोड को फिर से लिखने होता है।

+0

वरीयता आपका पूरा अधिकार है, 'नहीं में डी' एक नौसिखिया को डी में '(नहीं के) के रूप में भ्रमित कर सकता है, जबकि' के में नहीं 'में कोई अस्पष्टता नहीं है –

+0

मैं यह भी तर्क दूंगा कि यह' पायथनिक 'है जिस तरह से 'इन नहीं' को एक [ऑपरेटर] के रूप में सूचीबद्ध किया गया है (http://docs.python.org/2/reference/expressions.html#not-in)। –

+0

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

2

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

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

यहाँ की यह में इन परिवर्तनों के साथ अपने, मैं भी if बयान अभिव्यक्ति आप था जो अगर कुंजी शब्दकोश — में पहले से ही है वहाँ ऐसा करने के लिए और भी आसान निहित तरीके हैं देखने के लिए जाँच करता है सरल बनाया एक काम संस्करण है, लेकिन इस रास्ता अब के लिए काफी अच्छा है।

d = {} 
file = open("filename.txt", "r") 
readline = file.readline().rstrip() 
while readline: 
    lst = readline.split(" ") # split into list like ['AAA', 'x', '111'] 
    k = lst[0] # first item 
    v = lst[2] # third item 
    if k not in d: # new key? 
     d[k] = [] # initialize value 
    d[k].append(v) 
    readline = file.readline().rstrip() 

print 'd:', d 

आउटपुट:

d: {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']} 
-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)