Эффективный способ удалить пустые списки из списков? - PullRequest
16 голосов
/ 03 июля 2011

Каков наиболее эффективный способ удалить все пустые List[] объекты из всех List, которые появляются в выражении на разных уровнях? Пустой List[] должен быть удален, только если он является элементом другого List.

1 Ответ

21 голосов
/ 03 июля 2011

Эндрю и Алексей указывают, что использование expr //. x_List :> DeleteCases[x, {}, Infinity], как было в моем предыдущем ответе, также удалит {} в blah[{f[{}]}], тогда как он должен оставить его нетронутым, поскольку его голова f, а не List.Решение, благодаря Леониду, состоит в том, чтобы не использовать ReplaceRepeated, а Replace вместо того, чтобы производить замены на всех уровнях от 0 до Infinity:

Replace[expr, x_List :> DeleteCases[x, {}], {0, Infinity}]

Причинапочему Replace работает, а ReplaceRepeated - не видно из этого небольшого примера.Рассмотрим expr = {a, {}, {b, {}}, c[d, {}]}; в его TreeForm

enter image description here

Replace работах, начиная сначала с самых внутренних выражений, т. Е. List[b,{}] и c[d,{}], иработает вверх до верхнего узла.На каждом уровне проверить голову так же просто, как посмотреть вверх на узел прямо вверху и посмотреть, соответствует ли он List.Если это так, примените правило и поднимитесь на уровень, иначе ничего не делайте и поднимитесь на уровень.В результате получается окончательное дерево:

enter image description here

ReplaceRepeated (//.), с другой стороны, работает, начиная с самого верхнего узла и проходя вниз по дереву.предыдущее решение начинается с проверки, является ли первый узел List, а если да, то применяется DeleteCases, и оно перемещается вниз по дереву, беспощадно заменяя все найденные {}. Обратите внимание, что оно не проверяет, является лиглавы внутренних выражений также совпадают с List, потому что этот обход выполняется DeleteCases, а не ReplaceRepeated. Когда //. перемещается к последующим нижним узлам, заменять больше нечего, и он быстро завершается.дерево, которое можно получить с помощью предыдущего решения:

enter image description here

Обратите внимание, что {} внутри c[d, {}] также был удален. Это связано исключительно с тем, что DeleteCases(с указанием уровня {0,Infinity} перемещается вниз по дереву. Действительно, если бы первая голова была чем-то отличным от List, она пропустила бы ее и перешла на следующий уровень, из которого только {} в {b, {}} соответствует.с помощью expr2 = f[a, {}, {b, {}}, c[d, {}]] получаем

enter image description here

Обратите внимание, что в текущем решении с Replace мы используем DeleteCases со спецификацией уровня по умолчанию, которая является первым уровнемтолько.Поэтому он не проверяет и не удаляет пустые списки глубже, чем на первом уровне, а это именно то, что нам здесь нужно.

Несмотря на то, что мы использовали первый узел, чтобы объяснить, почему он не работает, рассуждение справедливо длякаждый узел.Леонид объясняет эти понятия более подробно в своей книге

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...