将任意时髦的嵌套列表expr
映射到函数unflatten
的最简单方法是什么,以便expr==unflatten@@Flatten@expr
?
动机:
Compile
只能处理完整数组(我刚刚学到的东西 - 但不是错误信息),因此我的想法是将unflatten
与扁平表达式的编译版本一起使用:
fPrivate=Compile[{x,y},Evaluate@Flatten@expr];
f[x_?NumericQ,y_?NumericQ]:=unflatten@@fPrivate[x,y]
解决不太常见问题的示例: 我实际需要做的是计算给定多元函数的所有导数,直到某个顺序。对于这种情况,我这样修理:
expr=Table[D[x^2 y+y^3,{{x,y},k}],{k,0,2}];
unflatten=Module[{f,x,y,a,b,sslot,tt},
tt=Table[D[f[x,y],{{x,y},k}],{k,0,2}] /.
{Derivative[a_,b_][_][__]-> x[a,b], f[__]-> x[0,0]};
(Evaluate[tt/.MapIndexed[#1->sslot[#2[[1]]]&,
Flatten[tt]]/. sslot-> Slot]&) ]
Out[1]= {x^2 y + y^3, {2 x y, x^2 + 3 y^2}, {{2 y, 2 x}, {2 x, 6 y}}}
Out[2]= {#1, {#2, #3}, {{#4, #5}, {#5, #7}}} &
这是有效的,但既不优雅也不一般。
编辑:以下是aaz提供的解决方案的“工作保障”版本:
makeUnflatten[expr_List]:=Module[{i=1},
Function@Evaluate@ReplaceAll[
If[ListQ[#1],Map[#0,#1],i++]&@expr,
i_Integer-> Slot[i]]]
它很有魅力:
In[2]= makeUnflatten[expr]
Out[2]= {#1,{#2,#3},{{#4,#5},{#6,#7}}}&
答案 0 :(得分:6)
您显然需要保存有关列表结构的一些信息,因为Flatten[{a,{b,c}}]==Flatten[{{a,b},c}]
。
如果ArrayQ[expr]
,则列表结构由Dimensions[expr]
提供,您可以使用Partition
重新构建它。 E.g。
expr = {{a, b, c}, {d, e, f}};
dimensions = Dimensions[expr]
{2,3}
unflatten = Fold[Partition, #1, Reverse[Drop[dimensions, 1]]]&;
expr == unflatten @ Flatten[expr]
(Partition
手册页实际上有一个名为unflatten
的类似示例。)
如果expr
不是数组,您可以尝试:
expr = {a, {b, c}};
indexes = Module[{i=0}, If[ListQ[#1], Map[#0, #1], ++i]& @expr]
{1, {2, 3}}
slots = indexes /. {i_Integer -> Slot[i]}
{#1, {#2, #3}}
unflatten = Function[Release[slots]]
{#1, {#2, #3}} &
expr == unflatten @@ Flatten[expr]
答案 1 :(得分:1)
我不确定你要用Compile做什么。当你想在数值上非常快速地评估程序或函数表达式时使用它,所以我认为它不会在这里有所帮助。如果重复计算D [f,...]会妨碍您的表现,您可以预先计算并存储类似的内容
Table[d[k]=D[f,{{x,y},k}],{k,0,kk}];
然后调用d [k]得到第k个导数。
答案 2 :(得分:1)
我只想更新aaz和Janus的优秀解决方案。看来,至少在Mac OSX上的Mathematica 9.0.1.0中,赋值(参见aaz的解决方案)
{i_Integer -> Slot[i]}
失败。但是,如果我们使用
{i_Integer :> Slot[i]}
相反,我们成功了。当然,同样适用于Janus的“工作保障”版本中的ReplaceAll
电话。
为了更好的衡量,我包括我自己的功能。
unflatten[ex_List, exOriginal_List] :=
Module[
{indexes, slots, unflat},
indexes =
Module[
{i = 0},
If[ListQ[#1], Map[#0, #1], ++i] &@exOriginal
];
slots = indexes /. {i_Integer :> Slot[i]};
unflat = Function[Release[slots]];
unflat @@ ex
];
(* example *)
expr = {a, {b, c}};
expr // Flatten // unflatten[#, expr] &
在函数中使用原始表达式似乎有点像作弊,但正如aaz所指出的,我们需要来自原始表达式的一些信息。虽然你不需要它 all ,但为了拥有一个{em> single 函数,unflatten
,一切都是必要的。
我的应用程序与Janus的类似:我正在调用Simplify
来调用张量。使用ParallelTable
我可以显着提高性能,但我破坏了过程中的张量结构。这为我提供了一种快速重建原始张量的方法,简化了。