从不同级别的表达式中出现的所有List[]
中删除所有空List
个对象的最有效方法是什么?只有当List[]
是另一个List
本身的元素时,才应删除空{{1}}。
答案 0 :(得分:21)
安德鲁和阿列克谢指出,使用expr //. x_List :> DeleteCases[x, {}, Infinity]
,就像我之前的回答一样,也会删除{}
中的blah[{f[{}]}]
,而它应该保持不变,因为它的头部是{{} 1}},而不是f
。感谢Leonid,解决方案是不使用List
,而是使用ReplaceRepeated
代替从Replace
到0
的所有级别进行替换:
Infinity
从这个小例子中可以看出Replace[expr, x_List :> DeleteCases[x, {}], {0, Infinity}]
工作原因和Replace
的原因。在ReplaceRepeated
expr = {a, {}, {b, {}}, c[d, {}]};
TreeForm
首先从最里面的表达式开始工作,即Replace
和List[b,{}]
,然后向上工作到顶部节点。在每个级别,检查头部就像查看上面的节点一样简单,看它是否与c[d,{}]
匹配。如果是,则应用规则并向上移动一个级别,否则不执行任何操作并向上移动一个级别。这导致最终树:
List
(ReplaceRepeated
,另一方面,从最顶层的节点开始并遍历树。先前的解决方案首先检查第一个节点是否为{{1}如果是,则应用//.)
并向下移动树,无情地替换它可以找到的每个List
。请注意,它不会检查内部表达式的头部是否也匹配{{ 1}},因为此遍历由DeleteCases
完成,而不是{}
。当List
移动到后续的较低节点时,没有什么可以替换它并且它会快速退出。这就是树那个人得到了以前的解决方案:
请注意,DeleteCases
内的ReplaceRepeated
也已被删除。这完全是因为//.
(级别规范{}
向下移动树。事实上,如果第一个头部不是c[d, {}]
,它就会跳过它并移至下一级,其中只有DeleteCases
中的{0,Infinity}
才匹配。要使用List
进行演示,我们会得到
请注意,在使用{}
的当前解决方案中,我们使用{b, {}}
和默认级别规范,这是第一级。因此,它不会检查和删除比第一级更深的空列表,这正是我们在这里所需要的。
虽然我们使用第一个节点来解释它失败的原因,但推理适用于每个节点。 Leonid在his book
中更详细地解释了这些概念