Python 如何将列表的字符串表示形式转换为列表?

Python 如何将列表的字符串表示形式转换为列表?,python,string,Python,String,我想知道最简单的方法是如何将如下列表的字符串表示形式转换为列表: x = '[ "A","B","C" , " D"]' 即使用户在逗号之间加空格,在引号内加空格,我也需要处理并将其转换为: x = ["A", "B", "C", "D"] 我知道我可以使用strip()和split()剥离空格,并检查是否有非字母字符。但是代码变得

我想知道最简单的方法是如何将如下列表的字符串表示形式转换为
列表

x = '[ "A","B","C" , " D"]'
即使用户在逗号之间加空格,在引号内加空格,我也需要处理并将其转换为:

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

我知道我可以使用
strip()
split()
剥离空格,并检查是否有非字母字符。但是代码变得非常混乱。是否有我不知道的快速功能?

有一个快速解决方案:

x = eval('[ "A","B","C" , " D"]')
可以通过以下方式删除列表元素中不需要的空白:

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

eval
是危险的-您不应该执行用户输入

如果您有2.6或更新版本,请使用ast而不是eval:

>>> import ast
>>> ast.literal_eval('["A","B" ,"C" ," D"]')
["A", "B", "C", " D"]
一旦你有了它,
strip
string

如果您使用的是较旧版本的Python,则可以通过一个简单的正则表达式非常接近您想要的:

>>> x='[  "A",  " B", "C","D "]'
>>> re.findall(r'"\s*([^"]*?)\s*"', x)
['A', 'B', 'C', 'D']
这不如ast解决方案好,例如,它不能正确处理字符串中的转义引号。但它很简单,不涉及危险的评估,如果您使用的是没有ast的较旧Python,那么它可能足以满足您的需要

>>> import ast
>>> x = '[ "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\u eval
可以安全地计算表达式节点或包含Python文本或容器显示的字符串。提供的字符串或节点只能由以下Python文本结构组成:字符串、字节、数字、元组、列表、dicts、booleans和
None


如果您知道列表只包含带引号的字符串,那么这个pyparsing示例将为您提供剥离字符串列表(甚至保留原始的Unicode字符串)


如果您的列表可以有更多的数据类型,甚至在列表中包含列表,那么您将需要一个更完整的语法,如pyparsing wiki,它将处理元组、列表、整数、浮点和带引号的字符串。将使用Python版本返回到2.4。

假设所有输入都是列表,并且输入中的双引号实际上不重要,这可以通过简单的regexp替换来完成。它有点perl-y,但工作起来很有魅力。还请注意,输出现在是一个unicode字符串列表,您没有指定需要它,但考虑到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']
junkers变量包含我们不需要的所有字符的已编译regexp(表示速度),使用]作为需要一些反斜杠技巧的字符。 sub用零替换所有这些字符,并在逗号处拆分结果字符串

请注意,这也会从内部条目u'[“oh no”]'-->[u'ohno']中删除空格。如果这不是您想要的,则需要对regexp进行一些增强

只要有一个字符串化的字典列表,该模块就是一个更好的解决方案。
json.load(您的_数据)
函数可用于将其转换为列表

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

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

为了使用json进一步完成@Ryan的回答,这里发布了一个非常方便的转换unicode的函数:

带双引号或单引号的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']

我想用regex提供一个更直观的模式化解决方案。 下面的函数将包含任意字符串的字符串化列表作为输入

逐步解释: 删除所有空格、括号和值分隔符(前提是它们不是要提取的值的一部分,否则会使正则表达式更复杂)。然后在单引号或双引号上拆分清理后的字符串,并获取非空值(或奇数索引值,无论首选项如何)


testsample:“['21'、'foo''6'、'0'、'A']”

因此,在所有答案之后,我决定对最常用的方法计时:

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

所以最后regex赢了

如果只是一维列表,则无需导入任何内容:

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

只需从列表的字符串表示形式中切掉第一个和最后一个字符,即可保存.strip()fcn(请参见下面的第三行)

mylist=[1,2,3,4,5,'baloney','alfalfa'] >>>strlist=str(mylist) ['1','2','3','4','5','baloney','alfalfa'] >>>mylistfromstring=(strlist[1:-1]。拆分(',')) >>>mylistfromstring[3] '4' >>>对于mylistfromstring中的条目: ... 打印(条目) ... 类型(条目) ... 1. 2. 3. 4. 5. “胡说八道” “紫花苜蓿”
受上面使用基本python包的一些答案的启发,我比较了几个(使用python 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
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
方法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:不导入

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

我很失望地看到,我认为可读性最差的方法是性能最好的方法。。。在使用最可读的选项时要考虑权衡。对于工作负载的类型,我使用python for,我通常重视可读性而不是性能稍高的选项,但通常情况下这取决于它。

并且使用纯python-不导入任何库

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

在处理存储为DataFrame的刮取数据时,可能会遇到这样的问题

如果值的列表显示为文本,则此解决方案的效果很好

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

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

Output: ['A', 'B', 'C', 'D']
不需要外部库


这通常发生在您将存储为字符串的列表加载到CSV时

如果您的列表以类似OP ASQUEST的形式存储在CSV中:

x = '[ "A","B","C" , " D"]'
以下是如何将其加载回列表:

import csv
with open('YourCSVFile.csv') as csv_file:
    reader = csv.reader(csv_file, delimiter=',')
    rows = list(reader)

listItems = rows[0]

listItems
现在是list

这仍然会保留引号内的空格这是对任意代码执行的公开邀请,除非你绝对确信输入永远是100%可信的,否则千万不要这样做或做类似的事情。我可以使用这个建议,因为我知道我的数据总是采用那种格式,而且是一项数据处理工作。这就是我需要的。谢谢。你到底想做什么?也许有一个更好的方法来解决这个问题
x = '[ "A","B","C" , " D"]'
import csv
with open('YourCSVFile.csv') as csv_file:
    reader = csv.reader(csv_file, delimiter=',')
    rows = list(reader)

listItems = rows[0]