将列表的字符串表示转换为列表

时间:2009-12-12 18:19:04

标签: python string

我想知道将string列表转换为list的最简单方法是什么:

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

即使用户在逗号和引号内的空格之间放置空格也是如此。我需要处理它:

x = ["A", "B", "C", "D"] 
在Python中

我知道我可以使用拆分运算符删除strip()split()的空格并检查非字母表。但是代码变得非常糟糕。有一个我不知道的快速功能吗?

19 个答案:

答案 0 :(得分:592)

>>> 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表达式的字符串。提供的字符串或节点可能只包含以下Python文字结构:字符串,数字,元组,列表,dicts,布尔值和None。

答案 1 :(得分:69)

eval很危险 - 您不应该执行用户输入。

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

>>> 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解决方案好,例如它无法正确处理字符串中的转义引号。但它很简单,不涉及危险的评估,并且如果你使用的是较旧的Python,可能对你的目的而言足够好。

答案 2 :(得分:56)

只要有字符串化的字典列表,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'}]

答案 3 :(得分:12)

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

答案 4 :(得分:6)

假设您的所有输入都是列表,并且输入中的双引号实际上无关紧要,可以使用简单的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变量包含我们不想要的所有字符的编译正则表达式(用于速度),使用]作为字符需要一些反斜杠技巧。 re.sub将所有这些字符替换为空,我们将结果字符串拆分为逗号。

请注意,这也会从内部条目中删除空格u'[“oh no”]'---> [u'ohno']。如果这不是你想要的,那么regexp需要加强一点。

答案 5 :(得分:6)

使用numpy这是一种非常简单的方法

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

给出

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

答案 6 :(得分:6)

有一个快速解决方案:

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

可以通过以下方式删除列表元素中不需要的空格:

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

答案 7 :(得分:6)

不导入任何内容;

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

ls = x.strip('][').split(',')

答案 8 :(得分:4)

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

>>> 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上的this one,它将处理元组,列表,整数,浮点数和引用字符串。将使用Python版本回到2.4。

答案 9 :(得分:2)

为了使用json进一步完成@Ryan的回答,转换unicode的一个非常方便的功能就是这里发布的一个: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']

答案 10 :(得分:1)

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

逐步说明: 您删除所有whitespacing,包围和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"]"

答案 11 :(得分:1)

在处理存储为Pandas DataFrame的抓取数据时,您可能会遇到这种问题。

如果值列表以文本形式出现,则此解决方案的工作方式类似于魅力。

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

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

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

不需要外部库。

答案 12 :(得分:1)

从以上一些适用于基本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

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

我很失望地看到我认为可读性最差的方法是性能最好的方法...使用最易读的选项时要权衡考虑...针对我使用python的工作负载类型因为我通常将可读性比性能更高的选项看重,但通常情况下,它取决于。

答案 13 :(得分: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

所以最终regex赢了!

答案 14 :(得分:0)

通过从列表的字符串表示中切下第一个和最后一个字符,您可以节省.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'>

答案 15 :(得分:0)

和纯python-不导入任何库

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

答案 16 :(得分:0)

当您将存储为字符串的列表加载到 CSV 时,通常会发生这种情况

如果您的列表以 OP 要求的格式存储在 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 现在是列表

答案 17 :(得分:0)

无需导入任何内容,无需评估。对于大多数基本用例,您可以在一行中完成此操作,包括原始问题中给出的用例。

一个班轮

l_x = [i.strip() for i in x[1:-1].replace('"',"").split(',')]

说明

x = '[ "A","B","C" , " D"]'
# str indexing to eliminate the brackets
# replace as split will otherwise retain the quotes in returned list
# split to conv to list
l_x = x[1:-1].replace('"',"").split(',')

输出

for i in range(0, len(l_x)):
    print(l_x[i])
# vvvv output vvvvv
'''
 A
B
C 
  D
'''
print(type(l_x)) # out: class 'list'
print(len(l_x)) # out: 4

您可以根据需要使用列表理解来解析和清理此列表。

l_x = [i.strip() for i in l_x] # list comprehension to clean up
for i in range(0, len(l_x)):
    print(l_x[i])
# vvvvv output vvvvv
'''
A
B
C
D
'''

嵌套列表

如果你有嵌套列表,它会变得更烦人。不使用正则表达式(这将简化替换),并假设您想返回一个扁平列表(和 zen of python says flat is better than nested):

x = '[ "A","B","C" , " D", ["E","F","G"]]'
l_x = x[1:-1].split(',')
l_x = [i
    .replace(']', '')
    .replace('[', '')
    .replace('"', '')
    .strip() for i in l_x
]
# returns ['A', 'B', 'C', 'D', 'E', 'F', 'G']

如果你需要保留嵌套列表,它会变得有点难看,但仍然可以通过 re 和列表理解来完成:

import re
x = '[ "A","B","C" , " D", "["E","F","G"]","Z", "Y", "["H","I","J"]", "K", "L"]'
# clean it up so regex is simpler
x = x.replace('"', '').replace(' ', '') 
# look ahead for the bracketed text that signifies nested list
l_x = re.split(r',(?=\[[A-Za-z0-9\',]+\])|(?<=\]),', x[1:-1])
print(l_x)
# flatten and split the non nested list items
l_x0 = [item for items in l_x for item in items.split(',') if not '[' in items]
# convert the nested lists to lists
l_x1 = [
    i[1:-1].split(',') for i in l_x if '[' in i 
]
# add the two lists 
l_x = l_x0 + l_x1

最后一个解决方案适用于任何以字符串形式存储的列表,无论是否嵌套。

答案 18 :(得分:-1)

让我们假设您的字符串是t_vector = [34,54,52,23],并且您想将其转换为列表。您可以使用以下2个步骤:

ls = t_vector.strip('][')
t_vector = ls.split(' ')

t_vector包含列表。