Ale*_*kov 16 wolfram-mathematica
List[]从List不同级别的表达式中出现的所有s中删除所有空对象的最有效方法是什么?List[]只有当它是另一个List自身的元素时才应该删除空.
abc*_*bcd 21
安德鲁和阿列克谢指出,expr //. x_List :> DeleteCases[x, {}, Infinity]按照我在之前的回答中使用也将删除{}in blah[{f[{}]}],而它应该保持不动,因为它的头部f不是List.感谢Leonid,解决方案是不使用ReplaceRepeated,而是通过以下方式Replace在所有级别进行替换:0Infinity
Replace[expr, x_List :> DeleteCases[x, {}], {0, Infinity}]
Run Code Online (Sandbox Code Playgroud)
从这个小例子可以看出Replace工作原因和原因ReplaceRepeated.考虑expr = {a, {}, {b, {}}, c[d, {}]};在其TreeForm

Replace首先从最里面的表达式开始工作,即List[b,{}]和c[d,{}],然后向上工作到顶部节点.在每个级别,检查头部就像查看上面的节点一样简单,看它是否匹配List.如果是,则应用规则并向上移动一个级别,否则不执行任何操作并向上移动一个级别.这导致最终树:

ReplaceRepeated(//.)另一方面,通过从最顶层节点开始并遍历树来工作.先前的解决方案首先检查第一个节点是否为a List,如果是,则DeleteCases应用它然后向下移动树,无情地替换每次{}它可以找到.请注意,它并不检查内表达的头也匹配List,因为这种穿越是做DeleteCases,而不是ReplaceRepeated当//.移动到后续的下级节点,没有什么更多的来代替,并很快退出.这是使用上一个解决方案得到的树:

请注意,{}内部c[d, {}]也已被删除.这完全是因为DeleteCases(水平规格{0,Infinity}在树下向下移动.事实上,如果第一个头部不是List,它会跳过它并移动到下一个级别,其中只有{}in {b, {}}是匹配为了展示expr2 = f[a, {}, {b, {}}, c[d, {}]],我们得到了

请注意,在当前的解决方案中Replace,我们使用DeleteCases默认级别规范,这仅是第一级.因此,它不会检查和删除比第一级更深的空列表,这正是我们在此需要的.
虽然我们使用第一个节点来解释它失败的原因,但推理适用于每个节点.列昂尼德在他的书中更详细地解释了这些概念