2012-10-27 1 views
10

संभव डुप्लिकेट ASCII करने के लिए यूनिकोड से तार के जटिल शब्दकोश कन्वर्ट:
How to get string Objects instead Unicode ones from JSON in Python?पायथन:

मैं JSON API कॉल से पार्स बहु स्तरीय शब्दकोशों के रूप में इनपुट के एक बहुत कुछ है। तार सभी यूनिकोड में हैं जिसका अर्थ है कि u'stuff like this' बहुत सारे हैं। मैं परिणामों के साथ खेलने के लिए jq का उपयोग कर रहा हूं और इन परिणामों को ASCII में परिवर्तित करने की आवश्यकता है।

मैं जानता हूँ कि मैं एक समारोह में लिख सकते हैं तो बस ऐसा कन्वर्ट करने के लिए:

def convert(input): 
    if isinstance(input, dict): 
     ret = {} 
     for stuff in input: 
      ret = convert(stuff) 
    elif isinstance(input, list): 
     ret = [] 
     for i in range(len(input)) 
      ret = convert(input[i]) 
    elif isinstance(input, str): 
     ret = input.encode('ascii') 
    elif : 
     ret = input 
    return ret 

यह और भी सही है? निश्चित नहीं। यही वह नहीं है जिसे मैं आपसे पूछना चाहता हूं।

मैं जो पूछ रहा हूं वह यह है कि यह समस्या का एक सामान्य ब्रूट-फोर्स समाधान है। इसके लिए अवश्य ही एक बेहतर तरीका होना चाहिए। ' एक और पाइथोनिक तरीका। मैं एल्गोरिदम पर कोई विशेषज्ञ नहीं हूं, लेकिन यह विशेष रूप से तेज़ नहीं दिखता है।

तो क्या कोई बेहतर तरीका है? या यदि नहीं, तो क्या यह कार्य बेहतर हो सकता है ...?


पोस्ट-जवाब संपादित

Mark Amery's answer सही है लेकिन मैं इसे का एक संशोधित संस्करण पोस्ट करने के लिए करना चाहते हैं। उनकी समारोह अजगर पर काम करता है 2.7+ और मैं 2.6 पर हूँ तो यह परिवर्तित करने के लिए किया था:

def convert(input): 
    if isinstance(input, dict): 
     return dict((convert(key), convert(value)) for key, value in input.iteritems()) 
    elif isinstance(input, list): 
     return [convert(element) for element in input] 
    elif isinstance(input, unicode): 
     return input.encode('utf-8') 
    else: 
     return input 
+1

यदि आप पाइथन 2 पर हैं, तो यूनिकोड 'str' का उदाहरण नहीं है, बल्कि 'यूनिकोड' का उदाहरण नहीं है। साथ ही, 'सूची' और 'dict' प्रसंस्करण में, आप इसे गलत कर रहे हैं। – agf

+0

सूची के मामले में, आप किसी भी पुनरावर्तनीय को संभालने पर विचार करना चाहेंगे। किसी भी मामले में, यदि आप इनपुट में एक्स के लिए 'ret = [convert (x) के साथ if स्टेटमेंट की उस शाखा को प्रतिस्थापित कर सकते हैं]। इसके अलावा, अपने शब्दकोश केस की जांच करें। 'ret' में केवल उसमें शामिल होगा जो शब्दकोश में अंतिम कुंजी को परिवर्तित करता है। –

+0

@MichaelMior आपके द्वारा वर्णित तरीके से किसी भी पुनरावर्तनीय को संभालने में समस्या यह है कि सभी पुनरावृत्तियों सूची-जैसी नहीं हैं। उदाहरण के लिए, शब्दकोश इटेरिएबल हैं, लेकिन इनपुट में एक्स के लिए 'ret = [convert (x) इनपुट]' स्पष्ट रूप से नहीं है कि हम चाहते हैं कि 'इनपुट' एक शब्दकोश है। –

उत्तर

23

Recursion तरह से यहां से जाने के लिए की तरह लगता है, लेकिन अगर आप अजगर 2.xx पर हैं तो आप जाँच करना चाहते हैं unicode के लिए, str नहीं (str प्रकार बाइट्स की एक स्ट्रिंग का प्रतिनिधित्व करता है, और unicode यूनिकोड वर्णों की एक स्ट्रिंग टाइप करता है, न तो दूसरे से विरासत मिलता है और यह यूनिकोड-प्रकार स्ट्रिंग है जो उनके सामने एयू के साथ दुभाषिया में प्रदर्शित होते हैं) ।

आपके पोस्ट कोड में थोड़ा वाक्यविन्यास त्रुटि भी है (पिछला elif:else होना चाहिए), और आप उस स्थिति में उसी संरचना को वापस नहीं कर रहे हैं जहां इनपुट या तो एक शब्दकोश या सूची है। (एक शब्दकोश के मामले में, आप अंतिम कुंजी के रूपांतरित संस्करण को वापस कर रहे हैं; किसी सूची के मामले में, आप अंतिम तत्व के रूपांतरित संस्करण को वापस कर रहे हैं। न तो सही है!)

आप कर सकते हैं समझ का उपयोग कर अपने कोड को सुंदर और पायथनिक भी बनाएं।

यहाँ है, तो, मैं क्या सलाह देते हैं है:

def convert(input): 
    if isinstance(input, dict): 
     return {convert(key): convert(value) for key, value in input.iteritems()} 
    elif isinstance(input, list): 
     return [convert(element) for element in input] 
    elif isinstance(input, unicode): 
     return input.encode('utf-8') 
    else: 
     return input 

एक अंतिम बात। मैंने encode('ascii') से encode('utf-8') बदल दिया। मेरा तर्क निम्नानुसार है: ASCII वर्ण सेट में केवल वर्ण वाले किसी भी यूनिकोड स्ट्रिंग को उसी बाइट स्ट्रिंग द्वारा दर्शाया जाएगा जब ASCII में एन्कोड किया गया था, जैसे कि utf-8 में एन्कोड किया गया था, इसलिए ASCII के बजाय utf-8 का उपयोग करके कुछ भी तोड़ नहीं सकता है और परिवर्तन तब तक अदृश्य हो जाएगा जब तक कि यूनिकोड स्ट्रिंग्स आप केवल ASCII वर्णों के उपयोग से निपट रहे हों। हालांकि, यह परिवर्तन फंक्शन के दायरे को पूरे यूनिकोड चरित्र सेट से वर्णों के तारों को संभालने में सक्षम होने के लिए बढ़ाता है, केवल एएससीआईआईआई के बजाय, ऐसी चीज कभी भी जरूरी होनी चाहिए।

+1

+1। आप रिकर्सन के बारे में टिप्पणी के अलावा :) रिकर्सन लगभग किसी भी प्रकार के पेड़ ट्रैवर्सल, और अधिकांश पार्सिंग समस्याओं के लिए उपयोगी है। रिकर्सन अक्सर "जाने का तरीका" होता है, खासकर जब यह कार्यात्मक प्रोग्रामिंग की बात आती है। –

+1

@ जोएल कॉर्नेट मेला पर्याप्त है। मेरी टिप्पणी व्यापक रूप से एंटी-रिकर्सन होने का मतलब नहीं थी; मैं देख सकता हूं कि पुनरावृत्ति पेड़ के ट्रैवर्सल समस्याओं में समझ में आता है, जिसमें से मुझे लगता है कि बहुत सी पार्सिंग समस्याएं सबसेट हैं। मैं इस खेल के लिए बिल्कुल नया हूं और एक compsci पृष्ठभूमि से नहीं, इसलिए मैं अभी तक उस प्रकृति की किसी भी समस्या में नहीं आया है। मैंने जो रिकर्सन देखा है, उसके उदाहरण व्यर्थ और संकुचित होते हैं, और उन परिस्थितियों पर लागू होते हैं जहां पुनरावृत्ति स्पष्ट होगी। यह पहली बार है जब मैं अचानक चला गया 'व्हाओ, रिकर्सन * वास्तव में चीज़ों को सरल बनाता है *, जो मेरे लिए रोमांचक था। :) –

+0

धन्यवाद, यह वाकई अच्छा है। इस सवाल में किसी भी उत्तर से काफी बेहतर है कि यह माना जाता है कि यह एक डुप्लिकेट है। – Dreen