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

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