2009-12-12 43 views
246

Tôi đã tự hỏi những cách đơn giản nhất là chuyển đổi một danh sách string như sau để một list:Chuyển đổi danh sách liệt kê trong Python

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

Ngay cả trong trường hợp người sử dụng đặt chỗ ở giữa các dấu phẩy, và dấu cách bên trong dấu ngoặc kép. Tôi cũng cần xử lý điều đó để:

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

bằng Python.

Tôi biết tôi có thể chia không gian với strip()split() bằng toán tử tách và kiểm tra các bảng chữ cái không. Nhưng mã đã nhận được rất kludgy. Có một chức năng nhanh mà tôi không biết?

+3

gì là bạn thực sự cố gắng để thực hiện? Có lẽ một cách tốt hơn nhiều so với việc cố gắng chuyển đổi cú pháp danh sách Python thành một danh sách thực tế ... –

+0

Bạn đang sử dụng phiên bản Python nào? –

+2

@Nicholas Knight: Tôi đang cố gắng xử lý dữ liệu nhập của người dùng trong ứng dụng cũ mà tất cả các danh sách được nhập dưới dạng danh sách unicode có dấu ngoặc vuông. @Mark Byers, tôi đang sử dụng python 2.6 để phương pháp tiếp cận ast.literal hoạt động tốt nhất – harijay

Trả lời

403
>>> 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:

Với ast.literal_eval, bạn có thể yên tâm đánh giá một nút biểu hoặc một chuỗi có chứa một biểu Python. Chuỗi hoặc nút được cung cấp chỉ có thể bao gồm các cấu trúc chữ viết Python sau: chuỗi, số, bộ, danh sách, dấu gạch ngang, booleans và None.

+2

Mỗi bình luận dưới đây, điều này là nguy hiểm vì nó chỉ đơn giản là chạy bất cứ điều gì python là trong chuỗi. Vì vậy, nếu ai đó đặt một cuộc gọi để xóa tất cả mọi thứ trong đó, nó hạnh phúc sẽ. –

+0

Câu trả lời hay, tôi đã vật lộn với vấn đề này trong một giờ cho đến khi tìm thấy câu trả lời này. –

5

Có một giải pháp nhanh chóng:

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

khoảng trắng không mong muốn trong các yếu tố danh sách có thể được gỡ bỏ theo cách này:

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

điều này sẽ vẫn bảo vệ không gian bên trong các dấu ngoặc kép – tosh

+10

Đây là lời mời mở để thực thi mã tùy ý, KHÔNG BAO GIỜ làm điều này hoặc bất cứ điều gì như nó trừ khi bạn biết tuyệt đối chắc chắn rằng đầu vào sẽ luôn được tin cậy 100%. –

+0

@tosh: nó sẽ không. –

9
import ast 
l = ast.literal_eval('[ "A","B","C" , " D"]') 
l = [i.strip() for i in l] 
50

Các eval là nguy hiểm - bạn không nên thực hiện đầu vào của người dùng.

Nếu bạn có 2.6 hoặc mới hơn, sử dụng ast thay vì eval:

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

Khi bạn đã có, strip các dây.

Nếu bạn đang ở trên một phiên bản cũ của Python, bạn có thể nhận được rất gần với những gì bạn muốn với một biểu thức chính quy đơn giản:

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

Đây không phải là tốt như các giải pháp ast, ví dụ nó không xử lý một cách chính xác các dấu nháy trong chuỗi. Nhưng nó đơn giản, không liên quan đến một eval nguy hiểm, và có thể đủ tốt cho mục đích của bạn nếu bạn đang ở trên một Python cũ mà không cần ast.

+0

Bạn có thể cho tôi biết lý do tại sao bạn nói “The' eval' là nguy hiểm - bạn không nên thực thi đầu vào của người dùng. ”? Tôi đang sử dụng 3.6 –

+0

@AaryanDewan nếu bạn sử dụng 'eval' trực tiếp, nó sẽ đánh giá bất kỳ biểu thức python hợp lệ nào, có khả năng gây nguy hiểm. 'literal_eval' giải quyết vấn đề này bằng cách chỉ đánh giá cấu trúc chữ Python: chuỗi, số, tuples, danh sách, dicts, booleans và None. –

3

Nếu bạn biết rằng danh sách của bạn chỉ chứa chuỗi được trích dẫn, ví dụ pyparsing này sẽ cung cấp cho bạn danh sách các chuỗi bị tước (thậm chí giữ nguyên Unicode gốc).

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

Nếu danh sách của bạn có thể có nhiều kiểu dữ liệu, hoặc thậm chí chứa danh sách trong danh sách, sau đó bạn sẽ cần một hoàn chỉnh hơn ngữ pháp - như this one trên wiki pyparsing, mà sẽ xử lý các bộ, danh sách, ints, phao, và chuỗi được trích dẫn. Sẽ làm việc với các phiên bản Python trở lại 2.4.

+0

bạn sẽ cho tôi biết cách sử dụng "parseString(). AsList()", nếu tôi có loại chuỗi này: '["A", "B", "C", ["D"]]', như bạn đã nói rằng pyparsing có thể làm điều đó là tốt. nhưng dường như không tìm được cách đúng đắn để làm điều đó. –

+0

"Nếu danh sách của bạn có thể có nhiều kiểu dữ liệu hơn, hoặc thậm chí có chứa danh sách trong danh sách, thì bạn sẽ cần ngữ pháp hoàn chỉnh hơn" - vui lòng xem liên kết tôi đã cung cấp trong câu trả lời của mình cho trình phân tích cú pháp sẽ xử lý danh sách lồng nhau và nhiều loại dữ liệu khác . – PaulMcG

7

Giả sử tất cả đầu vào của bạn là danh sách và dấu ngoặc kép trong đầu vào thực sự không quan trọng, điều này có thể được thực hiện bằng thay thế regexp đơn giản. Đó là một chút perl-y nhưng hoạt động như một say mê.Cũng lưu ý rằng đầu ra bây giờ là một danh sách các chuỗi unicode, bạn không chỉ rõ rằng bạn cần điều đó, nhưng nó có vẻ hợp lý với đầu vào unicode.

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

Biến rác có chứa regexp được biên dịch (cho tốc độ) của tất cả các ký tự mà chúng tôi không muốn sử dụng] làm ký tự yêu cầu một số thủ thuật gạch chéo ngược. re.sub thay thế tất cả các ký tự này bằng không, và chúng ta chia chuỗi kết quả tại dấu phẩy.

Lưu ý rằng thao tác này cũng xóa không gian từ các mục nhập bên trong u '["oh no"]' ---> [u'ohno ']. Nếu đây không phải là những gì bạn muốn, regexp cần phải được canh một chút.

7

với numpy này đang làm việc một cách rất đơn giản

x = u'[ "A","B","C" , " D"]' 
list_string = str(x) 
import numpy as np 
print np.array(list_string) 

cho

>>> 
[ "A","B","C" , " D"] 
+4

Tính năng này không hoạt động. Nó chỉ đơn giản là tạo một mảng 0-d của chuỗi. Bất kỳ hoạt động mảng nào, chẳng hạn như truy cập một phần tử, không thành công với lỗi. – River

30

Module json là một giải pháp tốt hơn bất cứ khi nào có một chuyển đổi thành chuỗi danh sách các từ điển. Có thể sử dụng chức năng json.loads(your_data) để chuyển đổi nó thành danh sách.

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

Tương tự

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

tuy nhiên tôi không muốn danh sách trả về ở định dạng unicode. nhưng có vẻ như ngay cả khi tôi xóa u '' khỏi chuỗi nó vẫn xử lý dữ liệu dưới dạng unicode. –

+1

Điều này làm việc cho ints nhưng không cho chuỗi trong trường hợp của tôi bởi vì mỗi chuỗi được trích dẫn duy nhất không tăng gấp đôi trích dẫn, tiếng thở dài. –

Các vấn đề liên quan