Преобразовать строковое представление списка в список
Мне было интересно, что самый простой способ - преобразовать список string
, как показано ниже, в list
:
x = u'[ "A","B","C" , " D"]'
Даже если пользователь помещает пробелы между запятыми и пробелы внутри кавычек. Мне также нужно обработать это:
x = ["A", "B", "C", "D"]
в Python.
Я знаю, что я могу разбивать пробелы с помощью strip()
и split()
с помощью оператора split и проверять отсутствие алфавитов. Но код становился очень глупым. Есть ли быстрая функция, о которой я не знаю?
Ответы
Ответ 1
>>> 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: строк, чисел, кортежей, списков, диктов, логических значений и None.
Ответ 2
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.
Ответ 3
Модуль 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'}]
Ответ 4
import ast
l = ast.literal_eval('[ "A","B","C" , " D"]')
l = [i.strip() for i in l]
Ответ 5
Быстрое решение:
x = eval('[ "A","B","C" , " D"]')
Нежелательные пробелы в элементах списка могут быть удалены следующим образом:
x = [x.strip() for x in eval('[ "A","B","C" , " D"]')]
Ответ 6
Предполагая, что все ваши входы являются списками и что двойные кавычки на входе действительно не имеют значения, это можно сделать с помощью простой замены regexp. Это немного perl-y, но работает как шарм. Обратите также внимание на то, что вывод теперь представляет собой список строк в юникоде, вы не указали, что вам это нужно, но, похоже, это имеет смысл при вводе в 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 ']. Если это не то, что вы хотели, регулярное выражение должно быть немного сжато.
Ответ 7
Не импортируя ничего:
>>> x = u'[ "A","B","C" , " D"]'
>>> ls = x.strip('[]').replace('"', '').replace(' ', '').split(',')
>>> ls
['A', 'B', 'C', 'D']
Ответ 8
Если вы знаете, что ваши списки содержат только строки с кавычками, этот пример 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, которая будет обрабатывать кортежи, списки, ints, float и цитируемые строки. Будет работать с версиями Python до версии 2.4.
Ответ 9
с numpy
это работает очень просто.
x = u'[ "A","B","C" , " D"]'
list_string = str(x)
import numpy as np
print np.array(list_string)
дает
>>>
[ "A","B","C" , " D"]
Ответ 10
Для дальнейшего завершения ответа @Ryan с использованием json, одна очень удобная функция для преобразования юникода - та, которая размещена здесь: fooobar.com/questions/29132/...
например, с двойными или одинарными кавычками:
>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']
Ответ 11
Вдохновленный некоторыми ответами выше, что работа с базовыми пакетами Python, я сравнил производительность нескольких (используя Python 3.7.3):
Способ 1: аст
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 Значение читабельности по сравнению с чуть более производительным вариантом, но, как обычно, зависит.
Ответ 12
Я хотел бы предоставить более интуитивное решение для создания паттернов с помощью регулярных выражений. Приведенная ниже функция принимает в качестве входных данных строковый список, содержащий произвольные строки.
Пошаговое объяснение: вы удаляете все пробельные символы, скобки и разделители-значения (если они не являются частью значений, которые вы хотите извлечь, в противном случае регулярное выражение становится более сложным). Затем вы разбиваете очищенную строку на одинарные или двойные кавычки и принимаете непустые значения (или нечетные индексированные значения, независимо от предпочтений).
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 "]"
Ответ 13
Итак, следуя всем ответам, я решил выбрать наиболее распространенные методы:
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
Итак, в конце концов, регулярное выражение побеждает!
Ответ 14
Вы можете сохранить себя .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
и с чистым питоном - без импорта каких-либо библиотек
[x for x in x.split('[')[1].split(']')[0].split('"')[1:-1] if x not in[',',' , ',', ']]
Ответ 16
Предположим, что ваша строка t_vector = [34, 54, 52, 23] и вы хотите преобразовать ее в список. Вы можете использовать следующие 2 шага:
ls = t_vector.strip('][')
t_vector = ls.split(' ')
t_vector содержит список.