Мне нравится анализировать HTML с регулярными выражениями. Я не пытаюсь разбирать идиот HTML, который намеренно нарушен. Этот код является моим основным парсером (версия Perl):
$_ = join "",; tr/\n\r \t/ /s; s/\n/>\n/g; s/\n ?\n/\n/g;
s/^ ?\n//s; s/ $//s; print
Он называется htmlsplit, разбивает HTML на строки, с одним тегом или фрагментом текста в каждой строке. Затем линии могут быть обработаны другими текстовыми инструментами и сценариями, такими как grep , sed , Perl и т. Д. Я даже не шучу :) Наслаждайтесь.
Достаточно просто переписать мой скрипт Perl-all-first Perl в приятную поточную вещь, если вы хотите обрабатывать огромные веб-страницы. Но это действительно не обязательно.
Бьюсь об заклад, я заберусь для этого.
Против моего ожидая, что это получило некоторые upvotes, поэтому я предлагаю несколько правильных выражений:
/(<.*?>|[^<]+)\s*/g # get tags and text
/(\w+)="(.*?)"/g # get attibutes
Они хороши для XML / XHTML.
С небольшими вариациями он может справиться с беспорядочным HTML ... или сначала конвертировать HTML -> XHTML.
Лучший способ записи регулярных выражений - в Lex / Yacc стиль, а не непрозрачные однострочные или прокомментированные многострочные чудовища. Я не делал этого здесь; эти им едва ли нужны.
zip
является его собственным обратным! Если вы используете специальный оператор *.
>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)])
[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
Как это работает, вызывая zip
с аргументами:
zip(('a', 1), ('b', 2), ('c', 3), ('d', 4))
... за исключением того, что аргументы передаются в zip
напрямую (после преобразования в кортеж), поэтому нет необходимости беспокоиться о том, что количество аргументов слишком велико.
Вы также можете сделать
result = ([ a for a,b in original ], [ b for a,b in original ])
Он должен масштабироваться лучше. Особенно, если Python делает все возможное, чтобы не расширять списки, если это не нужно.
(Кстати, это делает 2-кортежи (пары) списков, а не список кортежей, например zip
).
Если генераторы вместо фактических списков в порядке, это будет делать следующее:
result = (( a for a,b in original ), ( b for a,b in original ))
Генераторы не пробиваются по списку, пока вы не спросите об каждом элементе, но на с другой стороны, они сохраняют ссылки на исходный список.
zip(*x)
. zip(*x)
требуется только один проход через цикл и не использует элементы стека.
– habnabit
17 November 2013 в 18:38
zip
, если прецедентом является то, что транспонированные данные используются и отбрасываются немедленно, в то время как исходные списки остаются в памяти намного дольше.
– Ekevoo
15 November 2015 в 07:55
Если у вас есть списки, которые не имеют одинаковой длины, вы можете не захотеть использовать zip в соответствии с ответом Patricks. Это работает:
>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)])
[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
Но с разными списками длины zip обрезает каждый элемент до длины кратчайшего списка:
>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', )])
[('a', 'b', 'c', 'd', 'e')]
Вы можете использовать карту без функции для заполнения пустые результаты с None:
>>> map(None, *[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', )])
[('a', 'b', 'c', 'd', 'e'), (1, 2, 3, 4, None)]
zip () немного быстрее, хотя.
map
работает так?
– Grijesh Chauhan
26 September 2013 в 16:53
Это только другой способ сделать это, но это очень помогло мне написать здесь:
Наличие этой структуры данных:
X=[1,2,3,4]
Y=['a','b','c','d']
XY=zip(X,Y)
Результат:
In: XY
Out: [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]
Чем больше pythonic способ распаковать его и вернуться к оригиналу, это, на мой взгляд, это:
x,y=zip(*XY)
Но это возвращает кортеж, поэтому, если вам нужен массив, вы можете использование:
xy=(list(x),list(y))
Так вы можете транспонировать кортеж 2x4 в кортеж 4x2.
>>> tuple(zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)]))
[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
Еще один способ подумать о unzip
или transpose
- преобразовать список строк в список столбцов.
pitchers = [('Nolan', 'Ryan'), ('Roger', 'Clements'), ('Schilling','Curt')]
first_names, last_names = zip(*pitchers)
In [45]: first_names
Out[45]: ('Nolan', 'Roger', 'Schilling')
In [46]: last_names
Out[46]: ('Ryan', 'Clements', 'Curt')
>>> original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> tuple([list(tup) for tup in zip(*original)])
(['a', 'b', 'c', 'd'], [1, 2, 3, 4])
Дает кортеж списков, как в вопросе.
list1, list2 = [list(tup) for tup in zip(*original)]
Распаковывает два списка.
Мне нравится использовать zip(*iterable)
(который является частью кода, который вы ищете) в моих программах:
def unzip(iterable):
return zip(*iterable)
Я нахожу unzip
более читаемым.
Поскольку он возвращает кортежи (и может использовать тонны памяти), трюк zip(*zipped)
кажется мне более умным, чем полезным.
Вот функция, которая на самом деле даст вам обратный zip.
def unzip(zipped):
"""Inverse of built-in zip function.
Args:
zipped: a list of tuples
Returns:
a tuple of lists
Example:
a = [1, 2, 3]
b = [4, 5, 6]
zipped = list(zip(a, b))
assert zipped == [(1, 4), (2, 5), (3, 6)]
unzipped = unzip(zipped)
assert unzipped == ([1, 2, 3], [4, 5, 6])
"""
unzipped = ()
if len(zipped) == 0:
return unzipped
dim = len(zipped[0])
for i in range(dim):
unzipped = unzipped + ([tup[i] for tup in zipped], )
return unzipped
zip([], [])
таким образом не дает вам[], []
. Это дает вам[]
. Если только... – user2357112 24 February 2014 в 14:06list1=[]; list2=[]
. – user2357112 26 February 2014 в 04:53zip
работает точно так же в Python 3, за исключением того, что он возвращает итератор вместо списка. Чтобы получить тот же результат, что и выше, вам просто нужно обернуть zip-вызов в списке:list(zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)]))
выведет[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
– MJeffryes 11 March 2015 в 15:11