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

2024-11-15 08:36:00
admin
原创
13
摘要:问题描述:我想知道将如下列表的字符串表示形式转换为的最简单方法是什么list:x = '[ "A","B","C" , " D"]' 即使在用户在逗号之间添加空格以及在引号内添加空格的情况下,我也需要处理这种情况并将其转换为:x ...

问题描述:

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

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

即使在用户在逗号之间添加空格以及在引号内添加空格的情况下,我也需要处理这种情况并将其转换为:

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

我知道我可以用strip()和去除空格split()并检查非字母字符。但代码变得非常混乱。有没有我不知道的快捷功能?


解决方案 1:

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

评估仅包含 Python 文字或容器显示的表达式节点或字符串。提供的字符串或节点只能由以下 Python 文字结构组成:字符串、字节、数字、元组、列表、字典、集合、布尔值NoneEllipsis

这可用于评估包含 Python 值的字符串,而无需自己解析值。它无法评估任意复杂的表达式,例如涉及运算符或索引的表达式。

解决方案 2:

json每当有字符串化的字典列表时,该模块都是更好的解决方案。该json.loads(your_data)函数可用于将其转换为列表。

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

解决方案 3:

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 解决方案好,例如它不能正确处理字符串中的转义引号。但它很简单,不涉及危险的 eval,如果您使用的是没有 ast 的旧版 Python,它可能足以满足您的目的。

解决方案 4:

受到上面一些使用基础 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

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

方法三:不导入

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 的工作负载类型,我通常更看重可读性而不是性能稍高的选项,但通常这取决于情况。

解决方案 5:

有一个快速的解决方案:

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

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

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

解决方案 6:

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

解决方案 7:

如果它只是一个一维列表,则无需导入任何内容即可完成此操作:

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

解决方案 8:

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

一句话

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

解释

x = '[ "A","B","C" , " D"]'
# String indexing to eliminate the brackets.
# Replace, as split will otherwise retain the quotes in the returned list
# Split to convert to a 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
'''

嵌套列表

如果你有嵌套列表,那就有点烦人了。如果不使用正则表达式(这会简化替换),并假设你想返回一个扁平列表(python 的禅宗认为扁平比嵌套好):

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

如果您需要保留嵌套列表,它会变得有点丑陋,但仍然可以使用正则表达式和列表理解来完成:

import re

x = '[ "A","B","C" , " D", "["E","F","G"]","Z", "Y", "["H","I","J"]", "K", "L"]'
# Clean it up so the regular expression 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

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

解决方案 9:

你可以这样做

**

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

** 最好的是接受的答案

虽然这不是一种安全的方法,但最好的答案是被接受的答案。在发布答案时并没有意识到评估的危险。

解决方案 10:

假设您的所有输入都是列表,并且输入中的双引号实际上无关紧要,则可以使用简单的正则表达式替换来完成此操作。它有点像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'] 中删除空格。如果这不是您想要的,则需要对正则表达式进行一些改进。

解决方案 11:

如果您知道您的列表仅包含带引号的字符串,则此 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 示例目录中的这个语法,它将处理元组、列表、整数、浮点数和带引号的字符串。

解决方案 12:

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

如果值列表以文本形式存在,则此解决方案非常有效。

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

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

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

不需要外部库。

解决方案 13:

这通常发生在将以字符串形式存储的列表加载到 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现在是列表

解决方案 14:

为了进一步使用 JSON 完成Ryan 的回答,此答案中有一个非常方便的转换 Unicode 的函数。

带双引号或单引号的示例:

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

解决方案 15:

json.loads()json 包是json.dumps()与 javascript 等效的方法JSON.parse()JSON.stringify()因此使用 json 解决方案可以让生活更简单

import json
a = '[ "A","B","C" , " D"]'
print(json.loads(a)) #['A', 'B', 'C', ' D']
b = ['A', 'B', 'C', ' D']
print(json.dumps(b)) # '["A", "B", "C", " D"]'

解决方案 16:

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

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

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',“foo”'6','0',“A”]”

解决方案 17:

因此,根据所有答案,我决定对最常用的方法进行计时:

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:    ", (time() - start) / reps)

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

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

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

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

因此最终正则表达式获胜!

解决方案 18:

您可以通过从列表的字符串表示形式中切掉第一个和最后一个字符来节省 .strip() 函数(参见下面的第三行):

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

解决方案 19:

使用纯 Python — — 不导入任何库:

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

解决方案 20:

如果您不想导入任何库,这是另一种解决方案:

x = '[ "A","B","C" , " D"]'
def toList(stringList):
  stringList = stringList.split('[')[1]# removes "["
  stringList = stringList.split(']')[0]# removes "]"
  stringList = stringList.split(',')#gets objects in the list
  return [text.strip()[1:-1] for text in stringList] #eliminate additional " or ' in the string.
toList(x)

输出:

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

该方法的缺点是,如果字符串中有逗号,则该方法无效,例如,如果您的输入是

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

你的输出将是

['A', '', '', 'C', ' D']

这不是你想要的。

解决方案 21:

这个解决方案比我在以前的答案中读到的一些解决方案更简单,但它需要匹配列表中的所有特征。

x = '[ "A","B","C" , " D"]'
[i.strip() for i in x.split('"') if len(i.strip().strip(',').strip(']').strip('['))>0]

输出:

['A', 'B', 'C', 'D']
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用