Zastanawiałem się, jaki jest najprostszy sposób na przekonwertowanie string
listy w następujący sposób list
:
x = u'[ "A","B","C" , " D"]'
Nawet w przypadku, gdy użytkownik wstawi spacje między przecinkami i spacje w cudzysłowie. Muszę sobie z tym poradzić również, aby:
x = ["A", "B", "C", "D"]
w Pythonie.
Wiem, że mogę usuwać spacje za pomocą operatora podziału strip()
i split()
korzystać z niego, a także sprawdzać, czy nie występują alfabety. Ale kod stawał się bardzo niezgrabny. Czy jest jakaś szybka funkcja, której nie jestem świadomy?
Odpowiedzi:
ast.literal_eval :
źródło
eval
, nieast.literal_eval
.ast.literal_eval
jest bezpieczniejszy niżeval
, ale tak naprawdę nie jest bezpieczny . Jak wyjaśniają najnowsze wersje dokumentacji : „Ostrzeżenie Możliwe jest zawieszenie interpretera Pythona na wystarczająco dużym / złożonym łańcuchu ze względu na ograniczenia głębokości stosu w kompilatorze AST Pythona”. W rzeczywistości może być możliwe uruchomienie dowolnego kodu poprzez ostrożny atak niszczący stos, chociaż o ile wiem, nikt nie buduje publicznego dowodu na to.json
Moduł jest lepszym rozwiązaniem, gdy istnieje stringified lista słowników. Za pomocą tejjson.loads(your_data)
funkcji można przekształcić ją w listę.podobnie
źródło
'["a","b"]'
ale nie działa"['a','b']"
.Jest
eval
to niebezpieczne - nie należy wykonywać danych wprowadzanych przez użytkownika.Jeśli masz wersję 2.6 lub nowszą, użyj ast zamiast eval:
Kiedy już to zrobisz,
strip
struny.Jeśli korzystasz ze starszej wersji Pythona, możesz zbliżyć się do tego, co chcesz, za pomocą prostego wyrażenia regularnego:
To nie jest tak dobre, jak rozwiązanie ast, na przykład nie obsługuje poprawnie cudzysłowów w ciągach. Ale to proste, nie wymaga niebezpiecznej ewaluacji i może być wystarczające dla twojego celu, jeśli używasz starszego Pythona bez astmy.
źródło
eval
jest niebezpieczne - nie powinieneś wprowadzać danych użytkownika”. Używam 3.6eval
bezpośrednio, oceni każde poprawne wyrażenie python, które jest potencjalnie niebezpieczne.literal_eval
rozwiązuje ten problem, oceniając jedynie literalne struktury Pythona: ciągi, liczby, krotki, listy, dykta, logiczne i Brak.źródło
Istnieje szybkie rozwiązanie:
Niepożądane białe znaki w elementach listy można usunąć w ten sposób:
źródło
Zainspirowany niektórymi powyższymi odpowiedziami, które działają z podstawowymi pakietami Pythona, porównałem wydajność kilku (używając Pythona 3.7.3):
Metoda 1: ast
Metoda 2: Json
Metoda 3: bez importu
Byłem rozczarowany, gdy zobaczyłem, że to, co uważałem za metodę o najgorszej czytelności, to metoda o najlepszej wydajności ... są pewne kompromisy, które należy wziąć pod uwagę, wybierając najbardziej czytelną opcję ... dla rodzajów obciążeń, w których zwykle używam Pythona czytelność wartości w porównaniu z nieco bardziej wydajną opcją, ale jak zwykle to zależy.
źródło
Jeśli jest to tylko lista jednowymiarowa, można to zrobić bez importowania czegokolwiek:
źródło
Zakładając, że wszystkie dane wejściowe są listami i że podwójne cudzysłowy w danych wejściowych nie mają znaczenia, można tego dokonać za pomocą prostej zamiany wyrażenia regularnego. To trochę perl-y, ale działa jak urok. Zauważ też, że wyjście jest teraz listą ciągów Unicode, nie określiłeś, że jest to potrzebne, ale wydaje się mieć sens biorąc pod uwagę dane wejściowe Unicode.
Zmienna junkers zawiera skompilowane wyrażenie regularne (dla szybkości) wszystkich znaków, których nie chcemy, użycie] jako znaku wymagało pewnych sztuczek z odwrotnym ukośnikiem. Re.sub zastępuje wszystkie te znaki niczym, a wynikowy ciąg dzielimy na przecinki.
Zauważ, że to również usuwa spacje z wewnętrznych wpisów u '[„oh no”] ”---> [u'ohno']. Jeśli nie tego chciałeś, regexp musi zostać nieco ulepszony.
źródło
Jeśli wiesz, że twoje listy zawierają tylko ciągi cytowane, ten przykład parsowania da ci listę pasowanych ciągów (nawet zachowując oryginalną Unicode).
Jeśli twoje listy mogą zawierać więcej typów danych, a nawet zawierać listy w obrębie list, będziesz potrzebować pełniejszej gramatyki - takiej jak ta na wiki pyparsing, która będzie obsługiwać krotki, listy, liczby całkowite, zmiennoprzecinkowe i ciągi cytowane. Będzie działał z wersjami Pythona od wersji 2.4.
źródło
parsePythonValue.py
Przykładem jest teraz na GitHub na github.com/pyparsing/pyparsing/blob/master/examples/...Aby uzupełnić odpowiedź @Ryan za pomocą jsona, jedną bardzo wygodną funkcją konwersji Unicode jest ta zamieszczona tutaj: https://stackoverflow.com/a/13105359/7599285
np. z podwójnymi lub pojedynczymi cytatami:
źródło
Chciałbym zapewnić bardziej intuicyjne rozwiązanie wzorcowania z regex. Poniższa funkcja przyjmuje jako dane wejściowe listę łańcuchową zawierającą dowolne ciągi znaków.
Wyjaśnienie krokowe: Usuwasz wszystkie spacje, braketing i separatory wartości (pod warunkiem, że nie są one częścią wartości, które chcesz wyodrębnić, w przeciwnym razie wyrażenie regularne będzie bardziej złożone). Następnie dzielisz oczyszczony ciąg na pojedyncze lub podwójne cudzysłowy i bierzesz niepuste wartości (lub nieparzyste wartości indeksowane, niezależnie od preferencji).
testample : „[„ 21 ”,„ foo ”„ 6 ”,„ 0 ”,„ A ”]„
źródło
oraz z czystym pythonem - bez importowania żadnych bibliotek
źródło
Możesz napotkać taki problem, mając do czynienia ze zeskrobanymi danymi przechowywanymi jako Pandas DataFrame.
To rozwiązanie działa jak urok, jeśli lista wartości jest obecna jako tekst .
źródło
Tak więc, podążając za wszystkimi odpowiedziami, postanowiłem ustalić najbardziej popularne metody:
W końcu regex wygrywa!
źródło
możesz zaoszczędzić sobie .strip () fcn, po prostu odcinając pierwszy i ostatni znak z reprezentacji ciągu listy (patrz trzeci wiersz poniżej)
źródło