Вопрос-Ответ

How to convert string representation of list to a list

Как преобразовать строковое представление списка в список

Мне было интересно, какой самый простой способ преобразовать строковое представление списка, подобное следующему, в 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: строк, байтов, чисел, кортежей, списков, dicts, наборов, логических значений, None и Ellipsis.


Это можно использовать для вычисления строк, содержащих значения 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, например, оно некорректно обрабатывает экранированные кавычки в строках. Но это просто, не требует опасной оценки и может быть достаточно хорошим для ваших целей, если вы используете более старый Python без ast.

Ответ 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

Метод 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, я обычно предпочитаю читаемость чуть более производительному варианту, но, как обычно, это зависит.

python string list