从列表中删除空列表的有效方法? [英] Efficient way to remove empty lists from lists?

查看:27
本文介绍了从列表中删除空列表的有效方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从出现在不同级别的表达式中的所有 List 中删除所有空 List[] 对象的最有效方法是什么?空的 List[] 只有当它是另一个 List 本身的元素时才应该被删除.

What is the most efficient way to remove all empty List[] objects from all of the Lists that appear in an expression at different levels? The empty List[] should be removed only if it is an element of another List itself.

推荐答案

Andrew 和 Alexey 指出使用 expr//.x_列表:>DeleteCases[x, {}, Infinity] 就像我在之前的答案中一样,也会删除 blah[{f[{}]}] 中的 {}>,而它应该保持不变,因为它的头部是 f,而不是 List.多亏了 Leonid,解决方案是不使用 ReplaceRepeated,而是使用 Replace,而是在从 0 的所有级别进行替换无限:

Andrew and Alexey point out that using expr //. x_List :> DeleteCases[x, {}, Infinity] as I had in my previous answer will also remove the {} in blah[{f[{}]}], whereas it should leave it untouched as its head is f, not a List. The solution, thanks to Leonid, is to not use ReplaceRepeated, but Replace instead with replacements being made at all levels from 0 through Infinity:

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

<小时>

为什么 Replace 有效而 ReplaceRepeated 无效的原因可以从这个小例子中看出.考虑 expr = {a, {}, {b, {}}, c[d, {}]}; 在它的 TreeForm


The reason why Replace works and ReplaceRepeated doesn't can be seen from this little example. Consider expr = {a, {}, {b, {}}, c[d, {}]}; in its TreeForm

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

Replace works by starting with the innermost expression(s) first, i.e., List[b,{}] and c[d,{}], and works upwards to the top node. At each level, checking the head is as simple as looking up to the node right above and see if it matches List. If it does, apply the rule and move up a level, else do nothing and move up a level. This results in a final tree:

ReplaceRepeated (//.) 另一方面,从最顶端的节点开始并向下遍历树.前面的解决方案首先检查第一个节点是否是 List,如果是,则应用 DeleteCases 并沿着树向下移动,无情地替换每个 {} 它可以找到.请注意,它不会检查内部表达式的头部是否也匹配 List,因为这种遍历是由 DeleteCases 完成的,而不是 ReplaceRepeated.当//.移动到后续的下层节点时,就没有什么可以替换的了,快速退出.这是使用上一个解决方案得到的树:

ReplaceRepeated (//.), on the other hand, works by starting with the top most node and traversing down the tree. The previous solution starts by checking if the first node is a List and if it is, then DeleteCases is applied and it moves down the tree, ruthlessly replacing every {} it can find. Note that it does not check if the heads of the inner expressions also match List, because this traversal is done by DeleteCases, not ReplaceRepeated. When //. moves to subsequent lower nodes, there is nothing more to replace and it exits quickly. This is the tree that one gets with the previous solution:

请注意,c[d, {}] 中的 {} 也已被删除.这完全是因为 DeleteCases(具有级别规范 {0,Infinity} 沿着树向下移动.事实上,如果第一个头不是 List,它会跳过它并移动到下一层,其中只有 {b, {}} 中的 {} 是匹配的. 用 expr2 = f[a, {}, {b, {}}, c[d, {}]] 演示,我们得到

Note that the {} inside c[d, {}] has also been removed. This is solely due to the fact that DeleteCases (with level specification {0,Infinity} moves down the tree. Indeed, if the first head had been something other than List, it would've skipped it and moved to the next level, of which only the {} in {b, {}} is a match. To demostrate with expr2 = f[a, {}, {b, {}}, c[d, {}]], we get

请注意,在当前带有 Replace 的解决方案中,我们使用带有默认级别规范的 DeleteCases,这只是第一级.因此,它不会比第一级更深入地检查和删除空列表,这正是我们在这里需要的.

Note that in the current solution with Replace, we use DeleteCases with the default level specification, which is the first level only. It does not, therefore, check for and delete empty lists deeper than on the first level, which is exactly what we need here.

虽然我们使用第一个节点来解释它失败的原因,但推理适用于每个节点.Leonid 在他的书

Although we used the first node to explain why it fails, the reasoning holds true for every node. Leonid explains these concepts in greater detail in his book

这篇关于从列表中删除空列表的有效方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆