सूची में स्ट्रिंग प्रतिनिधित्व सूची में कैसे परिवर्तित करें?


530

मैं सोच रहा था कि stringसूची को निम्नलिखित में बदलने का सबसे सरल तरीका क्या है list:

x = u'[ "A","B","C" , " D"]'

यहां तक ​​कि अगर उपयोगकर्ता अल्पविराम और उद्धरणों के अंदर रिक्त स्थान रखता है। मुझे इसे संभालने की आवश्यकता है:

x = ["A", "B", "C", "D"] 

अजगर में।

मुझे पता है कि मैं स्प्लिट ऑपरेटर के साथ रिक्त स्थान strip()का split()उपयोग कर सकता हूं और गैर अक्षर के लिए जांच कर सकता हूं । लेकिन कोड बहुत ही कर्कश हो रहा था। क्या कोई त्वरित कार्य है जिसके बारे में मुझे जानकारी नहीं है?


4
क्या आप वास्तव में पूरा करने की कोशिश कर रहे हैं? पायथन लिस्ट के सिंटैक्स को वास्तविक सूची में बदलने की कोशिश करने से बेहतर तरीका शायद है ...
निकोलस नाइट

1
आप पायथन के किस संस्करण का उपयोग कर रहे हैं?
मार्क बायर्स

2
@ नाइकोलस नाइट: मैं एक विरासत ऐप में उपयोगकर्ता इनपुट को संभालने की कोशिश कर रहा हूं, जहां सभी सूचियों को स्क्वायर पेरेंटिस के साथ यूनिकोड सूचियों के रूप में दर्ज किया गया था। @ मार्कर बायर्स, मैं अजगर 2.6 का उपयोग कर रहा हूं, इसलिए एस्ट्रोलाइटल दृष्टिकोण सबसे अच्छा काम करता है
harijay

जवाबों:


768
>>> import ast
>>> x = u'[ "A","B","C" , " D"]'
>>> x = ast.literal_eval(x)
>>> x
['A', 'B', 'C', ' D']
>>> x = [n.strip() for n in x]
>>> x
['A', 'B', 'C', 'D']

ast.literal_eval :

Ast.literal_eval के साथ, आप सुरक्षित रूप से एक अभिव्यक्ति नोड या एक पायथन अभिव्यक्ति युक्त स्ट्रिंग का मूल्यांकन कर सकते हैं। प्रदान की गई स्ट्रिंग या नोड में केवल निम्नलिखित पायथन शाब्दिक संरचनाएं शामिल हो सकती हैं: स्ट्रिंग्स, संख्याएँ, टुपल्स, सूचियाँ, डाइक, बूलियन और कोई नहीं।


6
नीचे टिप्पणी के अनुसार, यह खतरनाक है क्योंकि यह स्ट्रिंग में जो भी अजगर है बस चलाता है। इसलिए अगर कोई वहां हर चीज को डिलीट करने के लिए कॉल करता है, तो यह खुशी से होगा।
पॉल केंजोरा

16
@PaulKenjora: आप सोच रहे हैं eval, नहीं ast.literal_eval
user2357112

19
ast.literal_evalसे अधिक सुरक्षित है eval, लेकिन यह वास्तव में सुरक्षित नहीं है । के रूप में किए गए दस्तावेज़ों की हाल के संस्करण की व्याख्या: "चेतावनी यह पायथन के एएसटी संकलक में ढेर गहराई सीमाओं के कारण एक पर्याप्त रूप से बड़े / जटिल तार के साथ अजगर दुभाषिया दुर्घटना संभव है।" यह वास्तव में, एक सावधान स्टैक-स्मैशिंग हमले के माध्यम से मनमाना कोड चलाना संभव हो सकता है, हालांकि जहां तक ​​मुझे पता है कि कोई भी इसके लिए अवधारणा का सार्वजनिक प्रमाण नहीं बनाता है।
गर्भपात

ठीक है, लेकिन क्या होगा यदि सूची में उद्धरण नहीं हैं? जैसे [B का 4, 1 का G]
sqp_125

84

jsonमॉड्यूल जब भी वहाँ एक है एक बेहतर समाधान है stringified शब्दकोशों की सूची। json.loads(your_data)समारोह में यह एक सूची में बदलने के लिए इस्तेमाल किया जा सकता।

>>> import json
>>> x = u'[ "A","B","C" , " D"]'
>>> json.loads(x)
[u'A', u'B', u'C', u' D']

उसी प्रकार

>>> x = u'[ "A","B","C" , {"D":"E"}]'
>>> json.loads(x)
[u'A', u'B', u'C', {u'D': u'E'}]

हालाँकि मैं यूनिकोड प्रारूप में दी गई सूची नहीं चाहता। लेकिन ऐसा लगता है कि अगर मैं स्ट्रिंग को हटा देता हूं तो भी यह डेटा को यूनिकोड मानता है।
मंसूर अकरम

7
यह चींटियों के लिए काम करता है, लेकिन मेरे मामले में तार के लिए नहीं क्योंकि प्रत्येक स्ट्रिंग एकल उद्धृत है उद्धृत नहीं, आह।
पॉल केंजोरा

4
@ पॉलकेनजोरा की टिप्पणी के अनुसार, यह काम करता है '["a","b"]'लेकिन इसके लिए नहीं "['a','b']"
स्किप्पी ले ग्रैंड गौरू

83

evalखतरनाक है - आप उपयोगकर्ता इनपुट पर अमल नहीं करना चाहिए।

यदि आपके पास 2.6 या नया है, तो eval के बजाय ast का उपयोग करें:

>>> import ast
>>> ast.literal_eval('["A","B" ,"C" ," D"]')
["A", "B", "C", " D"]

एक बार जब आपके पास है, stripतार।

यदि आप पाइथन के पुराने संस्करण पर हैं, तो आप एक साधारण नियमित अभिव्यक्ति के साथ जो चाहें प्राप्त कर सकते हैं।

>>> x='[  "A",  " B", "C","D "]'
>>> re.findall(r'"\s*([^"]*?)\s*"', x)
['A', 'B', 'C', 'D']

यह मूल समाधान जितना अच्छा नहीं है, उदाहरण के लिए यह स्ट्रिंग में बच गए उद्धरणों को सही ढंग से संभाल नहीं पाता है। लेकिन यह आसान है, एक खतरनाक साक्ष्य को शामिल नहीं करता है, और यदि आप बिना किसी पुराने पायथन पर हैं तो आपके उद्देश्य के लिए पर्याप्त अच्छा हो सकता है।


क्या आप मुझे बता सकते हैं कि आपने क्यों कहा " evalखतरनाक है - आपको उपयोगकर्ता इनपुट निष्पादित नहीं करना चाहिए।" मैं
आर्यन दीवान

1
@ आरण्यवन यदि आप evalसीधे उपयोग करते हैं, तो यह किसी भी मान्य अजगर अभिव्यक्ति का मूल्यांकन करेगा, जो संभावित खतरनाक है। literal_evalकेवल पायथन शाब्दिक संरचनाओं का मूल्यांकन करके इस समस्या को हल करता है: स्ट्रिंग्स, संख्याएं, टुपल्स, सूचियां, डीकट्स, बूलियन और कोई नहीं।
अभिषेक मेनन


10

एक त्वरित समाधान है:

x = eval('[ "A","B","C" , " D"]')

सूची तत्वों में अवांछित व्हाट्सएप को इस तरह हटाया जा सकता है:

x = [x.strip() for x in eval('[ "A","B","C" , " D"]')]

यह अभी भी उद्धरण के अंदर रिक्त स्थान को सुरक्षित रखेगा
tosh

17
यह मनमाने कोड निष्पादन के लिए एक खुला निमंत्रण है, कभी भी ऐसा या ऐसा कुछ भी न करें जब तक कि आप पूर्ण निश्चितता के साथ नहीं जानते कि इनपुट हमेशा 100% विश्वसनीय होगा।
निकोलस नाइट

1
मैं इस सुझाव का उपयोग कर सकता हूं क्योंकि मुझे पता था कि मेरा डेटा हमेशा उस प्रारूप में रहने वाला था और डेटा प्रोसेसिंग कार्य था।
मनीष रंजन

9

आधार पायथन पैकेज के साथ उस काम के ऊपर दिए गए कुछ जवाबों से प्रेरित होकर मैंने कुछ के प्रदर्शन की तुलना की (पायथन एक्स 3 का उपयोग करके):

विधि 1: ast

import ast
list(map(str.strip, ast.literal_eval(u'[ "A","B","C" , " D"]')))
# ['A', 'B', 'C', 'D']

import timeit
timeit.timeit(stmt="list(map(str.strip, ast.literal_eval(u'[ \"A\",\"B\",\"C\" , \" D\"]')))", setup='import ast', number=100000)
# 1.292875313000195

विधि 2: json

import json
list(map(str.strip, json.loads(u'[ "A","B","C" , " D"]')))
# ['A', 'B', 'C', 'D']

import timeit
timeit.timeit(stmt="list(map(str.strip, json.loads(u'[ \"A\",\"B\",\"C\" , \" D\"]')))", setup='import json', number=100000)
# 0.27833264000014424

विधि 3: कोई आयात नहीं

list(map(str.strip, u'[ "A","B","C" , " D"]'.strip('][').replace('"', '').split(',')))
# ['A', 'B', 'C', 'D']

import timeit
timeit.timeit(stmt="list(map(str.strip, u'[ \"A\",\"B\",\"C\" , \" D\"]'.strip('][').replace('\"', '').split(',')))", number=100000)
# 0.12935059100027502

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


9

यदि यह केवल एक आयामी सूची है, तो यह कुछ भी आयात किए बिना किया जा सकता है:

>>> x = u'[ "A","B","C" , " D"]'
>>> ls = x.strip('[]').replace('"', '').replace(' ', '').split(',')
>>> ls
['A', 'B', 'C', 'D']

8
सावधानी नोट: यह संभावित रूप से खतरनाक हो सकता है यदि सूची के अंदर के किसी तार के बीच में अल्पविराम हो।
हसन कमल

यह काम नहीं करेगा यदि आपकी स्ट्रिंग सूची सूचियों की सूची है
crypdick

@crypdick अच्छा बिंदु, उस बारे में एक नोट जोड़ा गया :)
15

6

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

import re
x = u'[ "A","B","C" , " D"]'
junkers = re.compile('[[" \]]')
result = junkers.sub('', x).split(',')
print result
--->  [u'A', u'B', u'C', u'D']

कबाड़ चर में सभी वर्णों के संकलित regexp (गति के लिए) होता है, जिसका हम उपयोग नहीं करना चाहते हैं] एक चरित्र के रूप में कुछ बैकस्लैश प्रवंचना की आवश्यकता होती है। Re.sub इन सभी वर्णों को कुछ भी नहीं बदलता है, और हम परिणामस्वरूप स्ट्रिंग को अल्पविराम में विभाजित करते हैं।

ध्यान दें कि यह भी प्रविष्टियाँ u '["ओह नहीं"] "---> [u'ohno'] से रिक्त स्थान को हटाता है। यदि यह वह नहीं है जो आप चाहते थे, तो regexp को थोडा ऊपर करने की आवश्यकता है।


4

यदि आप जानते हैं कि आपकी सूचियों में केवल उद्धृत स्ट्रिंग्स हैं, तो यह ज्वलंत उदाहरण आपको स्ट्रिप्ड स्ट्रिंग्स (यहां तक ​​कि मूल यूनिकोड-नेस के संरक्षण) की आपकी सूची देगा।

>>> from pyparsing import *
>>> x =u'[ "A","B","C" , " D"]'
>>> LBR,RBR = map(Suppress,"[]")
>>> qs = quotedString.setParseAction(removeQuotes, lambda t: t[0].strip())
>>> qsList = LBR + delimitedList(qs) + RBR
>>> print qsList.parseString(x).asList()
[u'A', u'B', u'C', u'D']

यदि आपकी सूचियों में अधिक डेटाटिप्स हो सकते हैं, या यहां तक ​​कि सूचियों के भीतर सूचियाँ भी हो सकती हैं, तो आपको एक अधिक संपूर्ण व्याकरण की आवश्यकता होगी - जैसे कि यह pyparsing wiki पर है, जो tuples, सूचियों, ints, floats, और उद्धृत स्ट्रिंग्स को हैंडल करेगा। 2.4 के पीछे पायथन संस्करणों के साथ काम करेंगे।


क्या आप मुझे बताएंगे कि कैसे "parseString ()। asList ()" का उपयोग करें, अगर मेरे पास इस तरह का स्ट्रिंग है: '["ए", "बी", "सी", ["डी"]]', 'के रूप में। ने कहा है कि pyparsing भी कर सकते हैं। लेकिन ऐसा लगता नहीं है कि इसे करने का सही तरीका मिल गया है।
मंसूर अकरम

"यदि आपकी सूचियों में अधिक डेटाटाइप हो सकते हैं, या यहां तक ​​कि सूचियों के भीतर सूचियां भी हो सकती हैं, तो आपको एक अधिक संपूर्ण व्याकरण की आवश्यकता होगी" - कृपया एक पार्सर के लिए मेरे उत्तर में दिए गए लिंक को देखें जो नेस्टेड सूचियों और विभिन्न अन्य प्रकार के डेटा को संभालेंगे।
पॉलएमसीजी

Pyparsing अब wikispaces पर होस्ट नहीं है। इसका parsePythonValue.pyउदाहरण अब GitHub पर github.com/pyparsing/pyparsing/blob/master/examples/…
PaulMcG

1

Json का उपयोग करते हुए @Ryan के उत्तर को पूरा करने के लिए, यूनिकोड को बदलने के लिए एक बहुत ही सुविधाजनक कार्य यहां पोस्ट किया गया है: https://stackoverflow.com/a/13105359/7599285

पूर्व के साथ डबल या एकल उद्धरण:

>print byteify(json.loads(u'[ "A","B","C" , " D"]')
>print byteify(json.loads(u"[ 'A','B','C' , ' D']".replace('\'','"')))
['A', 'B', 'C', ' D']
['A', 'B', 'C', ' D']

0

मैं रेगेक्स के साथ अधिक सहज पैटर्निंग समाधान प्रदान करना चाहूंगा। निम्न फ़ंक्शन इनपुट के रूप में एक कठोर सूची लेता है जिसमें मनमाने तार होते हैं।

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

def parse_strlist(sl):
import re
clean = re.sub("[\[\],\s]","",sl)
splitted = re.split("[\'\"]",clean)
values_only = [s for s in splitted if s != '']
return values_only

परीक्षण : "['21'," फू "'6', '0'," ए "]"


0

और शुद्ध अजगर के साथ - किसी भी पुस्तकालय का आयात नहीं करना

[x for x in  x.split('[')[1].split(']')[0].split('"')[1:-1] if x not in[',',' , ',', ']]

0

पंडों डेटाफ़्रेम के रूप में संग्रहीत स्क्रैप किए गए डेटा से निपटने के दौरान आप ऐसी समस्या में भाग सकते हैं।

यह समाधान आकर्षण की तरह काम करता है यदि मूल्यों की सूची पाठ के रूप में मौजूद है

def textToList(hashtags):
    return hashtags.strip('[]').replace('\'', '').replace(' ', '').split(',')

hashtags = "[ 'A','B','C' , ' D']"
hashtags = textToList(hashtags)

Output: ['A', 'B', 'C', 'D']

किसी बाहरी पुस्तकालय की आवश्यकता नहीं है।


-1

इसलिए, सभी उत्तरों के बाद मैंने सबसे सामान्य तरीकों का समय तय किया:

from time import time
import re
import json


my_str = str(list(range(19)))
print(my_str)

reps = 100000

start = time()
for i in range(0, reps):
    re.findall("\w+", my_str)
print("Regex method:\t", (time() - start) / reps)

start = time()
for i in range(0, reps):
    json.loads(my_str)
print("json method:\t", (time() - start) / reps)

start = time()
for i in range(0, reps):
    ast.literal_eval(my_str)
print("ast method:\t\t", (time() - start) / reps)

start = time()
for i in range(0, reps):
    [n.strip() for n in my_str]
print("strip method:\t", (time() - start) / reps)



    regex method:    6.391477584838867e-07
    json method:     2.535374164581299e-06
    ast method:      2.4425282478332518e-05
    strip method:    4.983267784118653e-06

तो अंत में रेगेक्स जीतता है!


-1

आप सूची के स्ट्रिंग प्रतिनिधित्व से पहले और अंतिम पात्रों को बंद करके केवल .strip () fcn को बचा सकते हैं (नीचे तीसरी पंक्ति देखें)

>>> mylist=[1,2,3,4,5,'baloney','alfalfa']
>>> strlist=str(mylist)
['1', ' 2', ' 3', ' 4', ' 5', " 'baloney'", " 'alfalfa'"]
>>> mylistfromstring=(strlist[1:-1].split(', '))
>>> mylistfromstring[3]
'4'
>>> for entry in mylistfromstring:
...     print(entry)
...     type(entry)
... 
1
<class 'str'>
2
<class 'str'>
3
<class 'str'>
4
<class 'str'>
5
<class 'str'>
'baloney'
<class 'str'>
'alfalfa'
<class 'str'>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.