Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wolfram mathematica 如何根据条件、功能方式动态创建列表_Wolfram Mathematica - Fatal编程技术网

Wolfram mathematica 如何根据条件、功能方式动态创建列表

Wolfram mathematica 如何根据条件、功能方式动态创建列表,wolfram-mathematica,Wolfram Mathematica,我仍然不擅长用Mathematica的函数方法处理列表。这里有一个小问题,我想问什么是解决这个问题的好方法 我要说的是,下面的清单由几点组成。因此,每个元素都是一个点的坐标(x,y) a = {{1, 2}, {3, 4}, {5, 6}} 我想遍历这个列表,每次我找到一个y坐标大于3.5的点,我想生成它的复共轭点。最后,我想返回生成的点的列表。因此,在上述示例中,有2个点将满足此条件。因此,最终列表将包含5个点,3个原始点和2个复杂的共轭点 我试过这个: If[#[[2]] > 3.5

我仍然不擅长用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}}
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]}
 ]
我尝试插入“展平”,但没有成功,因此,我发现自己有时会回到我以前的程序方式,并使用类似于Table和Do循环的方法,如下所示:

{{1, 2}, {3, 4}, {3, -4}, {5, 6}, {5, -6}}
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]}
]
我得到了和函数法相同的结果,但是在上面,因为我使用了一个临时变量,我每点计算一次

这是播种和收获的地方吗?我真的从来没有很好地理解过这两个函数。如果没有,您将如何以功能性的方式进行此操作


谢谢

一种方法是使用
序列

只需对您的解决方案进行一个小的修改:

If[#1[[2]] > 3.5, Unevaluated@Sequence[#1, {#1[[1]], -#1[[2]]}], #1] & /@ a
但是,普通的
ReplaceAll
可能更简单:

a /. {x_, y_} /; y > 3.5 :> Sequence[{x, y}, {x, -y}]
这种用法是
规则
规则延迟
具有属性
SequenceHold
的确切原因

回答更新1

我会分两步来做:

b = a /. {x_, y_} /; y > 3.5 :> Sequence[{x, y}, {x, -y}]
{Norm[#], #}& /@ b

在实际计算中,您可能希望单独使用范数,因此,
norm/@b
可能会执行

展平
使用第二个参数指定展平的深度。因此,您还可以执行以下操作

a = {{1, 2}, {3, 4}, {5, 6}};
Flatten[If[#[[2]] > 3.5, {#, {#[[1]], -#[[2]]}}, {#}] & /@ a, 1]
Do
循环中最严重的问题是使用
AppendTo
。如果
result
变长,这将非常缓慢。处理由于这种过程而增长的列表的标准方法是使用
eaw
Sow
。在本例中,您可以这样做

new = Reap[
  Do[If[el[[2]] > 3.5, Sow[{el[[1]], -el[[2]]}]],
  {el, a}]][[2, 1]];
Join[a, new]

若要回答您的编辑,请将
(或
模块
)一起使用,前提是您要多次使用昂贵的产品

以下是我对您编辑的问题的看法:

a = {{1, 2}, {3, 4}, {5, 6}};
Table[With[{n = Norm[x]}, 
  Unevaluated@Sequence[{n, x}, 
    If[x[[2]] > 3.5, {n, {1, -1} x}, Unevaluated@Sequence[]]]], 
 {x, a}]

可以修改上面的结构,以便在
Map
ReplaceAll
版本中使用,但我认为在这种情况下
Table
更清晰。未计算的序列有点烦人。你可以使用一些未定义的函数<代码> f>代码>然后用<代码>序列< <代码>结束替换<代码> f>代码>

,而Mathematica可以很好地模拟函数编程范例,你可以考虑使用Mathematica的原生范式——模式匹配:

a = {{1,2},{3,4},{5,6}}

b = a /. p:{x_, y_ /; y > 3.5} :> Sequence[p, {x, -y}]
然后,您可以进一步转换结果以包括
Norm
s:

c = Cases[b, p_ :> {Norm@p, p}]

毫无疑问,使用
Sequence
生成一个非常大的列表的效率不如预先分配一个大小正确的数组,然后使用元素分配更新它。然而,我通常更喜欢表达的清晰性,而不是这种微观优化,除非所述优化对我的应用程序至关重要。

Mark的Sow/Reap代码没有按请求的顺序返回元素。这是:

a = {{1, 2}, {3, 4}, {5, 6}};

Reap[
  If[Sow[#][[2]] > 3.5, Sow[# {1, -1}]] & /@ a;
][[2, 1]]

您可以使用join和Apply(@):

加入@@((如果[#[[2]]>3.5、{#、{#[[1]]、-#[[2]]}、{#}])&/@a)


+1,酷。实际上我在那里尝试了序列,但是是这样做的:如果[#[[2]]>3.5,序列[{#,{#[[1]],[2]}],[35;]&/@a,它也不起作用。我不知道这个骗局Unevaluated@Sequence这样地。我也喜欢你的第二个解决方案。谢谢。我有一个关于同一个问题的后续问题,我一直在努力以功能的方式去做。请参阅更新1。我实际上尝试了展平[…,1],但我只差了一{}。这就是我所尝试的:如果[#[[2]]>3.5、{#、{#[[1]]、#[[2]}、#]&/@a;展平[%,1];而且不起作用。我需要在上面的最后一个#周围添加一个额外的{}。我没看到。这些{{{}}会让人发疯:)。谢谢你的回答,谢谢大家的评论和回答。如果我能全部接受,我会的。我对编程和使用列表的“功能”方式了解得越多,我就越觉得它更强大。我正在经历我现在正在编写的一个演示,随着我学习的深入,我将一些过程代码更改为更“功能性”,我发现功能性方法更短,更不容易出错。我只是认为,与过程编程相比,函数编程需要更多的技能和时间,但这似乎是值得的。在Matlab中,通常使用预分配和赋值,但在Mathematica中是我们