목록의 문자열 표현을 목록으로 변환하는 방법은 무엇입니까?


531

string다음과 같은 목록을 다음으로 변환하는 가장 간단한 방법이 궁금 합니다 list.

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

사용자가 쉼표 사이에 공백을 넣고 따옴표 안에 공백을 넣는 경우에도 마찬가지입니다. 나는 그것을 처리해야합니다.

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

파이썬에서.

split 연산자를 사용하고 공백을 제거 strip()하고 split()알파벳이 아닌 것을 확인할 수 있다는 것을 알고 있습니다 . 그러나 코드는 매우 어려워졌습니다. 내가 모르는 빠른 기능이 있습니까?


4
실제로 무엇을 달성하려고합니까? 파이썬리스트 구문을 실제리스트로 변환하는 것보다 훨씬 더 좋은 방법이있을 것입니다.
Nicholas Knight

1
어떤 버전의 Python을 사용하고 있습니까?
Mark Byers

2
@ Nicholas Knight : 모든 목록이 사각형 괄호로 유니 코드 목록으로 입력 된 레거시 앱에서 사용자 입력을 처리하려고합니다. @ 마크 바이어스, 나는 ast.literal 접근 그래서 파이썬 2.6을 사용하고 가장 잘 작동
harijay

답변:


769
>>> 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을 사용하면 표현식 노드 또는 Python 표현식이 포함 된 문자열을 안전하게 평가할 수 있습니다. 제공된 문자열 또는 노드는 문자열, 숫자, 튜플, 목록, dicts, 부울 및 없음과 같은 Python 리터럴 구조로만 구성 될 수 있습니다.


6
아래의 설명에 따르면, 문자열에있는 파이썬을 단순히 실행하기 때문에 위험합니다. 따라서 누군가가 거기에있는 모든 것을 삭제하기 위해 전화를 걸면 행복하게됩니다.
Paul Kenjora

16
@PaulKenjora : 당신은 생각하고 eval,하지 ast.literal_eval.
user2357112는

19
ast.literal_eval이다 안전 보다는 eval,하지만 실제로 아니다 안전 . 최신 버전의 문서에서 설명한 바와 같이 : "경고 파이썬 AST 컴파일러의 스택 깊이 제한으로 인해 파이썬 인터프리터가 충분히 크거나 복잡한 문자열로 충돌 할 수 있습니다." 사실 아무도 아무도 그것에 대한 공개 개념 증명을 구축하지 않는 한 신중한 스택 스매싱 공격을 통해 임의의 코드를 실행할 수 있습니다.
abarnert

그러나 목록에 따옴표가 없으면 어떻게해야합니까? 예 : [B의 4, G의 1]
sqp_125

84

json있을 때마다 모듈은 더 나은 솔루션입니다 캐릭터 라인 사전의 목록. 이 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'}]

그러나 유니 코드 형식으로 반환 목록을 원하지 않습니다. 그러나 문자열에서 u ''를 제거하더라도 여전히 데이터를 유니 코드로 취급합니다.
Mansoor Akram

7
이것은 각 문자열이 작은 따옴표로 묶지 않은 한숨이기 때문에 정수에서는 작동하지만 문자열에서는 작동하지 않습니다.
Paul Kenjora

4
@PaulKenjora의 의견에 따라 작동 '["a","b"]'하지만 작동 하지 않습니다 "['a','b']".
Skippy le Grand Gourou 9

83

eval위험하다 - 당신이 사용자 입력을 실행하지 않아야합니다.

2.6 이상인 경우 eval 대신 ast를 사용하십시오.

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

일단 당신이 그것을 strip문자열.

이전 버전의 Python을 사용하는 경우 간단한 정규식을 사용하여 원하는 것에 매우 가까이 갈 수 있습니다.

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

이것은 ast 솔루션만큼 좋지 않습니다. 예를 들어 문자열에서 이스케이프 된 따옴표를 올바르게 처리하지 못합니다. 그러나 간단하고 위험한 평가를 포함하지 않으며 ast가없는 오래된 Python을 사용하는 경우 목적에 충분할 수 있습니다.


왜“ eval위험하다-사용자 입력을 실행해서는 안된다 ”고 말한 이유를 말씀해 주 시겠습니까? 3.6을 사용하고 있습니다
Aaryan Dewan

1
@AaryanDewan eval직접 사용하면 잠재적으로 위험한 모든 유효한 파이썬 표현식을 평가합니다. literal_eval문자열, 숫자, 튜플, 목록, dicts, 부울 및 없음과 같은 Python 리터럴 구조 만 평가하여이 문제를 해결합니다.
Abhishek Menon


10

빠른 해결책이 있습니다.

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

목록 요소에서 원하지 않는 공백은 다음과 같이 제거 할 수 있습니다.

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

이것은 여전히 ​​따옴표 안에 공백을 보존 할 것입니다
tosh

17
이것은 임의의 코드 실행에 대한 공개 초대입니다. 입력이 항상 100 % 신뢰할 수 있다는 것을 확실하게 알지 않는 한 절대로 이와 같은 것을 수행하지 마십시오.
Nicholas Knight

1
내 데이터가 항상 해당 형식으로되어 있고 데이터 처리 작업이라는 것을 알았으므로이 제안을 사용할 수 있습니다.
Manish Ranjan

9

기본 파이썬 패키지에서 작동하는 위의 답변 중 일부에서 영감을 얻었습니다 (파이썬 3.7.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

1 차원 목록 인 경우 아무 것도 가져 오지 않고 수행 할 수 있습니다.

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

8
주의 사항 :리스트 안의 문자열 중 쉼표가 있으면 위험 할 수 있습니다.
Hassan Kamal

문자열 목록이 목록 목록 인 경우 작동하지 않습니다.
crypdick

@crypdick 좋은 지적, 그것에 대해 메모를 추가 :)
ruohola

6

모든 입력이 목록이고 입력의 큰 따옴표가 실제로 중요하지 않다고 가정하면 간단한 정규 표현식 대체로 수행 할 수 있습니다. 약간 perl-y이지만 매력처럼 작동합니다. 또한 출력은 이제 유니 코드 문자열 목록이므로 필요하다고 지정하지 않았지만 유니 코드 입력이 주어진 것으로 이해됩니다.

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

junkers 변수에는 백 슬래시 트릭이 필요한 문자로]를 사용하여 원하지 않는 모든 문자의 컴파일 된 정규 표현식 (속도)이 포함되어 있습니다. re.sub는 이러한 모든 문자를 아무것도 대체하지 않으며 결과 문자열을 쉼표로 분할합니다.

또한 내부 항목 u '[ "oh no"]'---> [u'ohno ']에서 공백을 제거합니다. 이것이 원하는 것이 아니라면 정규 표현식을 약간 채워야합니다.


4

목록에 인용 된 문자열 만 포함되어 있다는 것을 알고 있다면이 pyparsing 예제는 스트립 된 문자열 목록을 제공합니다 (원래 유니 코드를 유지하더라도).

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

귀하의 목록에 더 많은 데이터 유형을 가지고, 또는 목록에서 목록을 포함 할 수있는 경우에, 당신은보다 완벽한 문법을해야합니다 - 같은 이 하나의 튜플,리스트,의 int, 수레, 그리고 인용 문자열을 처리 할 대한 파싱 위키. 파이썬 버전 2.4에서 작동합니다.


"parseString (). asList ()"를 사용하는 방법을 알려주시겠습니까? '[ "A", "B", "C", [ "D"]]'와 같은 문자열이있는 경우 pyparsing도 그렇게 할 수 있다고 언급했습니다. 그러나 o 올바른 방법을 찾지 못한 것 같습니다.
Mansoor Akram

"목록에 더 많은 데이터 유형이 있거나 목록에 목록이 포함되어 있으면 더 완전한 문법이 필요합니다."중첩 목록과 다양한 기타 데이터 유형을 처리하는 구문 분석기에 대한 답변에서 제공 한 링크를 참조하십시오.
PaulMcG

Pyparsing은 더 이상 wikispace에서 호스팅되지 않습니다. 이 parsePythonValue.py예제는 이제 github.com/pyparsing/pyparsing/blob/master/examples/
PaulMcG

1

json을 사용하여 @Ryan의 답변을 더 완성하려면 유니 코드를 변환하는 매우 편리한 함수 중 하나가 여기에 게시 된 것입니다 : https://stackoverflow.com/a/13105359/7599285

큰 따옴표 또는 작은 따옴표가있는 ex :

>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

정규식으로보다 직관적 인 패터닝 솔루션을 제공하고 싶습니다. 아래 함수는 임의의 문자열을 포함하는 문자열 목록을 입력으로 사용합니다.

단계별 설명 : 모든 공백, 대괄호 및 value_separators를 제거하십시오 (추출하려는 값의 일부가 아닌 경우 정규식을 더 복잡하게 만듭니다). 그런 다음 정리 된 문자열을 작은 따옴표 또는 큰 따옴표로 나누고 비어 있지 않은 값 (또는 환경 설정에 관계없이 홀수 색인 값)을 사용하십시오.

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

testsample : "[ '21',"foo " '6', '0',"A "]"


0

순수 파이썬으로-라이브러리를 가져 오지 않음

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

0

Pandas DataFrame으로 저장된 스크랩 된 데이터를 처리하는 동안 이러한 문제가 발생할 수 있습니다.

이 솔루션 은 값 목록이 text로 표시되는 경우 매력처럼 작동 합니다 .

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'>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.