在不评估保持表达式的情况下从列表中删除空列表的有效方法?

Ale*_*kov 6 wolfram-mathematica

以前的线程的有效方式删除空列表({}从列表)建议:

Replace[expr, x_List :> DeleteCases[x, {}], {0, Infinity}]
Run Code Online (Sandbox Code Playgroud)

使用Trott-Strzebonski就地评估技术,这种方法可以推广用于同时使用保持的表达式:

f1[expr_] := 
 Replace[expr, 
  x_List :> With[{eval = DeleteCases[x, {}]}, eval /; True], {0, Infinity}]
Run Code Online (Sandbox Code Playgroud)

此解决方案比基于以下方案的解决方案更有效ReplaceRepeated:

f2[expr_] := expr //. {left___, {}, right___} :> {left, right}
Run Code Online (Sandbox Code Playgroud)

但它有一个缺点:如果它们被包装,它会对持有的表达式进行求值List:

In[20]:= f1[Hold[{{}, 1 + 1}]]

Out[20]= Hold[{2}]
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:在{}不评估保持表达式的情况下从列表中删除所有空列表()的最有效方法是什么?只有当它是另一个自身的元素时,List[]应删除空对象.List


以下是一些时间安排:

In[76]:= expr = Tuples[Tuples[{{}, {}}, 3], 4];
First@Timing[#[expr]] & /@ {f1, f2, f3}
pl = Plot3D[Sin[x y], {x, 0, Pi}, {y, 0, Pi}]; 
First@Timing[#[pl]] & /@ {f1, f2, f3}

Out[77]= {0.581, 0.901, 5.027}

Out[78]= {0.12, 0.21, 0.18}
Run Code Online (Sandbox Code Playgroud)

定义:

Clear[f1, f2, f3];
f3[expr_] := 
  FixedPoint[
   Function[e, Replace[e, {a___, {}, b___} :> {a, b}, {0, Infinity}]], expr];
f1[expr_] := 
  Replace[expr, 
   x_List :> With[{eval = DeleteCases[x, {}]}, eval /; True], {0, Infinity}];
f2[expr_] := expr //. {left___, {}, right___} :> {left, right};
Run Code Online (Sandbox Code Playgroud)

Sas*_*sha 3

怎么样:

Clear[f3];
f3[expr_] := 
 FixedPoint[
  Function[e, 
   Replace[e, {a___, {}, b___} :> {a, b}, {0, Infinity}]],
   expr]
Run Code Online (Sandbox Code Playgroud)

它似乎符合规格:

In[275]:= f3[{a, {}, {b, {}}, c[d, {}]}]

Out[275]= {a, {b}, c[d, {}]}

In[276]:= f3[Hold[{{}, 1 + 1, {}}]]

Out[276]= Hold[{1 + 1}]
Run Code Online (Sandbox Code Playgroud)