首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不带For循环的单元化(列表咀嚼)

不带For循环的单元化(列表咀嚼)
EN

Stack Overflow用户
提问于 2010-07-22 01:29:31
回答 5查看 344关注 0票数 4

对于或同时循环在Mathematica代码总是让我感到有点脏,但我是困惑自己,试图做一些清单咀嚼所有的功能,并诉诸如下:

代码语言:javascript
复制
(* # Given a list of {x,y} pairs, transform the data as follows: every time 
   # there's a decrease in y-value from one datapoint to the next, say {x1,Y} 
   # followed by {x2,y}, add Y to the value of every datapoint on or after x2. *)
monotonify[data_] := Module[{data0, i, offset = 0},
  data0 = data;
  For[i = 2, i <= Length[data], i++,
    If[data[[i-1,2]] > data[[i,2]], offset += data[[i-1,2]]];
    data0[[i]] += {0,offset}];
  data0]

(把y-值看作是里程计读数,有时会不小心重新设定-很明显是因为这个值减少了,而这是校验仪不应该做的。因此,我们通过在每次重置之前将最后一个已知值添加到所有未来值来转换读数。

你如何用一种很好的功能风格来写单调呢?

(事实上,我并不认为上述For循环非常好,这可能是一种温和的强迫症。)

EN

回答 5

Stack Overflow用户

发布于 2010-07-22 09:14:32

好的,现在我已经按照最初的要求修正了处理输入的方法。

从一个示例数据集开始:

代码语言:javascript
复制
dataset = {{a, 1}, {b, 2}, {c, 3}, {d, 4}, {e, 5}, {f, 0}, {g, 4}, 
{h,5}, {i, 6}, {j, 7}, {k, 4}, {l, 7}, {m, 8}, {n, 9}, {o, 0}, {p,2}, 
{q, 3}};

采取转置:

代码语言:javascript
复制
trDataset = Transpose[dataset];

接下来,只对Y值进行操作的函数:

代码语言:javascript
复制
trDataset[[2]] = FoldList[Plus, dataset[[1, 2]], Map[Max[#, 0] &, Differences[dataset[[All, 2]]]]]

撤销换位:

代码语言:javascript
复制
dataset = Transpose[trDataset]

现在的输出

代码语言:javascript
复制
{{a, 1}, {b, 2}, {c, 3}, {d, 4}, {e, 5}, {f, 5}, {g, 9}, {h, 10}, {i, 
  11}, {j, 12}, {k, 12}, {l, 15}, {m, 16}, {n, 17}, {o, 17}, {p, 
  19}, {q, 20}}

我还没有测试过这个解决方案的性能。

编辑: OK,这是修复的基础,剩下的工作交给您@。这个单调性的版本只适用于一个数字列表,我还没有将它集成到我先前的建议中,即使用您的输入。

代码语言:javascript
复制
monotonify[series_] := 
 Split[series, Less] //. {a___, x_List, y_List, z___} /; 
     Last[x] > First[y] -> {a, x, y + Last[x], z} // Flatten

编辑2:另一个函数,它工作在一个数字列表上。这比我之前的尝试要快得多。

代码语言:javascript
复制
monotonify[series_] := 
Accumulate[Flatten[Map[Flatten[{#[[1]], Differences[#]}] &, 
       Split[series, Less]]]]
票数 4
EN

Stack Overflow用户

发布于 2010-07-24 19:17:55

以下是另一个解决方案:

代码语言:javascript
复制
Module[{corr, lasts},
 lasts = data[[All, 2]]; 
 corr = Prepend[Accumulate[MapThread[If[#1 > #2, #1, 0] &, {Most[lasts], Rest[lasts]}]], 0];
 Transpose[{data[[All, 1]], lasts + corr}]]

它计算一个校正向量,然后将其添加到给定数据点的y值中。

票数 3
EN

Stack Overflow用户

发布于 2010-07-22 02:07:43

一旦关闭了gauntlet,我就无法尝试它,但我认为For循环版本更简单:

代码语言:javascript
复制
mon00[{prev_,offset_}, next_] := {next, offset + If[prev > next, prev, 0]}
monotonify0[list_] := list + Rest[FoldList[mon00, {-Infinity,0}, list]][[All,2]]
monotonify[data_] := Transpose@{#1, monotonify0[#2]}& @@ Transpose@data

其思想是编写一个助手函数,它只对y-值的简单列表进行操作,然后使用双转置式成语对数据的第二列进行操作。

双转座式成语的方便参考

用于转换矩阵中的特定列,例如,用transformElementx替换4列矩阵第2列中的每个值x。

代码语言:javascript
复制
{#1, transformElement[#2], #3, #4}& @@@ matrix

如果您需要转换一个包含整个列的函数的列,请使用以下成语:

代码语言:javascript
复制
Transpose @ {#1, transformList[#2], #3, #4}& @@ Tranpose@matrix
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3305138

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档