【发布时间】:2011-07-24 10:11:43
【问题描述】:
我仍然不能很好地在 Mathematica 中以函数方式处理列表。这里有个小问题,想问问有什么好的函数式解决方法。
我已经说过以下由点组成的列表。因此每个元素都是一个点的坐标(x,y)。
a = {{1, 2}, {3, 4}, {5, 6}}
我想遍历这个列表,每次我找到一个 y 坐标 > 3.5 的点时,我都想生成它的复共轭点。最后,我想返回生成的点列表。因此,在上面的示例中,有 2 个点将满足此条件。因此,最终列表将有 5 个点,3 个原始点和 2 个复共轭点。
我试过了:
If[#[[2]] > 3.5, {#, {#[[1]], -#[[2]]}}, #] & /@ a
但我明白了
{{1, 2}, {{3, 4}, {3, -4}}, {{5, 6}, {5, -6}}}
您会在中间看到额外的 {},在我必须添加复共轭点的点周围。我希望结果是这样的:
{{1, 2}, {3, 4}, {3, -4}, {5, 6}, {5, -6}}
我尝试插入 Flatten,但没有奏效,因此,我发现自己有时会回到以前的程序方式,并像这样使用 Table 和 Do 循环之类的东西:
a = {{1, 2}, {3, 4}, {5, 6}}
result = {};
Do[
If[a[[i, 2]] > 3.5,
{
AppendTo[result, a[[i]]]; AppendTo[result, {a[[i, 1]], -a[[i, 2]]}]
},
AppendTo[result, a[[i]]]
],
{i, 1, Length[a]}
]
这给了我我想要的,但不是功能性解决方案,我不喜欢它。
解决此类列表操作的最佳功能方法是什么?
更新 1
使用上面相同的数据,假设我想在遍历列表时对每个点进行计算,并在构建列表时使用此计算。假设我想找到点的范数(位置向量),并使用它来构建一个列表,其每个元素现在都是 {norm, point}。并遵循与上述相同的逻辑。因此,唯一的区别是我在每一步都进行了额外的计算。
这是我使用提供的解决方案所做的:
a = {{1, 2}, {3, 4}, {5, 6}}
If[#[[2]] > 3.5,
Unevaluated@Sequence[ {Norm[#], #}, {Norm[#], {#[[1]], -#[[2]]}}],
{Norm[#], #}
] & /@ a
这给了我想要的:
{ {Sqrt[5],{1,2}}, {5,{3,4}}, {5,{3,-4}}, {Sqrt[61],{5,6}}, {Sqrt[61],{5,-6}} }
我遇到的唯一问题是,我在 3 个地方为同一点重复了对 Norm[#] 的调用。有没有办法在不重复计算的情况下做到这一点?
这就是我目前使用旧程序方式执行上述操作的方式:
a = {{1, 2}, {3, 4}, {5, 6}}
result = {};
Do[
o = Norm[a[[i]]];
If[a[[i, 2]] > 3.5,
{
AppendTo[result, {o, a[[i]]}]; AppendTo[result, {o, {a[[i, 1]], -a[[i, 2]]}}]
},
AppendTo[result, {o, a[[i]]}]
],
{i, 1, Length[a]}
]
我得到的结果与函数方式相同,但在上面,由于我使用了一个临时变量,所以我每点计算一次。
这是一个播种和收割之类的地方吗?我真的从来没有很好地理解这两个功能。如果没有,您将如何以功能方式执行此操作?
谢谢
【问题讨论】:
-
感谢大家的cmets和答案。如果我能全部接受,我会的。我对编程和使用列表的“功能性”方式了解得越多,我就越觉得它更强大。我正在查看我现在正在编写的演示,并在我了解更多信息时将我的一些程序代码更改为更具“功能性”,并且我发现功能方式更短且更不容易出错。我只是认为,与过程式编程相比,函数式编程需要更多的技能和时间,但这似乎是值得的。