पायथन में एक अर्धविराम से अलग स्ट्रिंग को एक शब्दकोश में विभाजित करना


84

मेरे पास एक स्ट्रिंग है जो इस तरह दिखता है:

"Name1=Value1;Name2=Value2;Name3=Value3"

क्या पायथन में एक अंतर्निहित वर्ग / फ़ंक्शन है जो उस स्ट्रिंग को ले जाएगा और एक शब्दकोश का निर्माण करेगा, जैसे कि मैंने यह किया है:

dict = {
    "Name1": "Value1",
    "Name2": "Value2",
    "Name3": "Value3"
}

मैं उपलब्ध मॉड्यूल के माध्यम से देखा है, लेकिन कुछ भी है कि मैच खोजने के लिए प्रतीत नहीं कर सकते।


धन्यवाद, मुझे पता है कि प्रासंगिक कोड को स्वयं कैसे बनाया जाता है, लेकिन चूंकि इस तरह के छोटे-छोटे समाधान आमतौर पर खदानों के होने की प्रतीक्षा में होते हैं (यानी कोई व्यक्ति लिखता है: Name1 = 'Value1 = 2';) आदि। तब मैं आमतौर पर कुछ पूर्व पसंद करता हूं- परीक्षण किया गया कार्य।

मैं खुद कर लूंगा तब।


क्या आपके प्रश्न को s = r'Name1='Value=2';Name2=Value2;Name3=Value3;Name4="Va\"lue;\n3"'इनपुट का समर्थन करने की आवश्यकता है (ध्यान दें: एक उद्धृत स्ट्रिंग के अंदर एक अर्धविराम, एक बैकस्लैश का उपयोग करके एक उद्धरण से बच \nजाता है , भागने का उपयोग किया जाता है, दोनों एकल और दोहरे उद्धरण का उपयोग किया जाता है)?
जफ्स

मेरा यह सवाल 6 साल से अधिक पुराना है, इसमें जो कोड शामिल है वह लंबे समय से बदल दिया गया है :) और नहीं, इसे उद्धरण के लिए समर्थन की आवश्यकता नहीं है। मैं सिर्फ खुद कुछ लिखने के बजाय एक प्रीबिल्ट फंक्शन करना चाहता था। हालाँकि, कोड लंबा चला गया है।
लास वी। कार्लसन

जवाबों:


144

कोई बिलिन नहीं है, लेकिन आप इसे काफी हद तक एक जनरेटर समझ के साथ पूरा कर सकते हैं:

s= "Name1=Value1;Name2=Value2;Name3=Value3"
dict(item.split("=") for item in s.split(";"))

[संपादित करें] आपके अपडेट से आपको संकेत मिलता है कि आपको उद्धरण को संभालने की आवश्यकता हो सकती है। यह चीजों को जटिल करता है, इस बात पर निर्भर करता है कि आप जिस सटीक प्रारूप की तलाश कर रहे हैं वह क्या है (कौन से उद्धरण चार्ट स्वीकार किए जाते हैं, कौन से चार्ट से बचते हैं)। आप यह देखने के लिए सीएसवी मॉड्यूल देखना चाहते हैं कि क्या यह आपके प्रारूप को कवर कर सकता है। यहां एक उदाहरण दिया गया है: (ध्यान दें कि इस उदाहरण के लिए एपीआई थोड़ा क्लंकी है, क्योंकि CSV को रिकॉर्ड के अनुक्रम के माध्यम से पुनरावृति करने के लिए डिज़ाइन किया गया है, इसलिए .next () कॉल मैं पहली पंक्ति को देखने के लिए बना रहा हूं। अपनी आवश्यकताओं के अनुरूप):

>>> s = "Name1='Value=2';Name2=Value2;Name3=Value3"

>>> dict(csv.reader([item], delimiter='=', quotechar="'").next() 
         for item in csv.reader([s], delimiter=';', quotechar="'").next())

{'Name2': 'Value2', 'Name3': 'Value3', 'Name1': 'Value1=2'}

अपने प्रारूप की सटीक संरचना के आधार पर, आपको अपने स्वयं के साधारण पार्सर को लिखना पड़ सकता है।


कोड उद्धृत करने का प्रयास नहीं करता है, कोशिश करें: s = "Name1='Value;2';Name2=Value2;Name3=Value3"(नोट: उद्धृत Name1मूल्य में अर्धविराम )।
jfs

1
मुझे नहीं पता कि दूसरा उदाहरण AttributeError: '_csv.reader' object has no attribute 'next'मेरे लिए क्यों फेंकता है। बेशक मैंने किया import csv
यंगजई

@ ब्रायन स्ट्रिंग के बजाय पूर्णांक के रूप में मूल्यों को संग्रहीत करने का कोई तरीका है?
चैडबायडथ

6

यह वही करने के करीब आता है जो आप चाहते थे:

>>> import urlparse
>>> urlparse.parse_qs("Name1=Value1;Name2=Value2;Name3=Value3")
{'Name2': ['Value2'], 'Name3': ['Value3'], 'Name1': ['Value1']}

2
यह टूट जाता है अगर वहाँ &या %इनपुट में है।
jfs

@jfs लेकिन स्ट्रिंग में दोनों शामिल नहीं हैं।
विशाल सिंह

@VishalSingh: StackOverflow पर अधिकांश आगंतुक Google से हैं और इसलिए यहाँ उत्तर केवल मूल पोस्टर के लिए नहीं हैं जिन्होंने प्रश्न पूछा है। अगर मैं यहां आया कि "सेमीकोलन-सेपरेटेड-स्ट्रिंग को एक शब्दकोश में, पाइथन में" कैसे पार्स किया जाए, तो मेरे तार हो सकते हैं &या %- बहुत कम से कम, यह ध्यान देने योग्य है कि इस तरह के तार के लिए जवाब काम नहीं करता है।
JFS


1

यह केवल स्ट्रिंग जॉइन और लिस्ट कॉम्प्रिहेंशन द्वारा किया जा सकता है

",".join(["%s=%s" % x for x in d.items()])

>>d = {'a':1, 'b':2}
>>','.join(['%s=%s'%x for x in d.items()])
>>'a=1,b=2'

-2
easytiger $ cat test.out test.py | sed 's/^/    /'
p_easytiger_quoting:1.84563302994
{'Name2': 'Value2', 'Name3': 'Value3', 'Name1': 'Value1'}
p_brian:2.30507516861
{'Name2': 'Value2', 'Name3': "'Value3'", 'Name1': 'Value1'}
p_kyle:7.22536420822
{'Name2': ['Value2'], 'Name3': ["'Value3'"], 'Name1': ['Value1']}
import timeit
import urlparse

s = "Name1=Value1;Name2=Value2;Name3='Value3'"

def p_easytiger_quoting(s):
    d = {}
    s = s.replace("'", "")
    for x in s.split(';'):
        k, v = x.split('=')
        d[k] = v
    return d


def p_brian(s):
    return dict(item.split("=") for item in s.split(";"))

def p_kyle(s):
    return urlparse.parse_qs(s)



print "p_easytiger_quoting:" + str(timeit.timeit(lambda: p_easytiger_quoting(s)))
print p_easytiger_quoting(s)


print "p_brian:" + str(timeit.timeit(lambda: p_brian(s)))
print p_brian(s)

print "p_kyle:" + str(timeit.timeit(lambda: p_kyle(s)))
print p_kyle(s)

यह प्रश्न का उत्तर नहीं देता है, क्योंकि यह उद्धरण को नहीं संभालता है। s = "Name1='Value1=2';Name2=Value2" and Csv` को आज़माएं (जैसा कि ब्रायन के स्वीकृत उत्तर में है) या parse_qs(काइल के रूप में) इसे सही मिलेगा, जबकि आपका एक उठाएगा ValueError। ओपी विशेष रूप से कहते हैं, "ऐसे छोटे समाधान आमतौर पर मेरा-फ़ील्ड होने की प्रतीक्षा कर रहे हैं", यही कारण है कि वह एक अंतर्निहित या अन्य परीक्षण किए गए समाधान चाहते हैं, और वह एक उदाहरण देता है जो आपके कोड को तोड़ देगा।
अबार्नेट

आह, मैंने वह नहीं देखा। फिर भी। यह अभी भी आपके सभी समाधानों से तेज होगा ताकि पुनरावृत्ति होने से पहले मुख्य स्ट्रिंग में उन लोगों को तैयार करने के लिए और हजारों बार प्रतिस्थापन फ़ंक्शन को याद किया जा सके। मैं अपडेट
करूंगा

मुझे यकीन नहीं है कि आप इसे कैसे तैयार करेंगे। लेकिन अगर आप ऐसा करते हैं, तो भी ऐसा लगता है कि ओपी एक साधारण समाधान से डरता है। क्या आप सुनिश्चित हैं कि आगे कोई अन्य खदानें नहीं हैं? क्या आप इसे ओपी की संतुष्टि के लिए साबित कर सकते हैं?
गाली

ठीक है, अब जब मैंने आपका संपादन देख लिया है ... पहला, s.replaceकुछ भी नहीं करता है; यह सिर्फ एक नया स्ट्रिंग देता है जिसे आप अनदेखा करते हैं। दूसरा, भले ही आपको यह सही लगे ( s = s.replace…), जो समस्या को ठीक नहीं करता है, यह सिर्फ इसके ऊपर एक नया जोड़ देता है। मेरे उदाहरण पर या ओपी की कोशिश करो।
गाली

विनिर्देश स्पष्ट रूप से, नमूना इनपुट वह अपने प्रश्न में आपका उल्लेख से निपटने में शामिल हैं Name='Value1=2';। और आपका कोड इसे संभालता नहीं है। और मुझे यकीन है कि आप कैसे स्वच्छ था किसी तरह कि बस के रूप में धीमी गति से किया जाएगा में यह पार्स करने के बिना नहीं कर रहा हूँ urlparseया csvपहली जगह में।
अबार्नेट

-2

यदि आपका मान 1, मान 2 वास्तविक मानों के लिए केवल प्लेसहोल्डर हैं, तो आप dict()फ़ंक्शन के साथ संयोजन में भी उपयोग कर सकते हैं eval()

>>> s= "Name1=1;Name2=2;Name3='string'"
>>> print eval('dict('+s.replace(';',',')+')')
{'Name2: 2, 'Name3': 'string', 'Name1': 1}

यह dict()फ़ंक्शन को सिंटैक्स को समझने के लिए मुस्कराते हुए है dict(Name1=1, Name2=2,Name3='string')। स्ट्रिंग में रिक्त स्थान (जैसे प्रत्येक अर्धविराम के बाद) को अनदेखा किया जाता है। लेकिन ध्यान दें कि स्ट्रिंग मानों को उद्धृत करने की आवश्यकता है।


धन्यवाद, upvote string.replace ने अच्छा काम किया। पता नहीं क्यों मैं विभाजित नहीं हो सका। मैंने t बॉक्स पर i = textcontrol.GetValue () किया, फिर o = i.split (';') लेकिन आउटपुट स्ट्रिंग के बदले स्वरूप के बारे में शिकायत की, लेकिन आउटपुट नहीं किया।
इकोनोविसी

1
s.replace(';'अगर ;कोई उद्धृत मूल्य के अंदर- आधारित समाधान टूट जाता है । eval बुराई है और यह इस मामले में अनावश्यक है।
jfs
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.