用于根据先前值过滤序列的惯用语clojure和Javascript表达式

Ita*_*man 2 javascript clojure

所以我有一个整数seq.我想选择所有其他元素,但前提是它前面的元素是正数.例如,给定此输入:

4, 9, -1, 8, 3, 20, -1, 7
Run Code Online (Sandbox Code Playgroud)

我想得到这个输出:

9, 20
Run Code Online (Sandbox Code Playgroud)

(上下文:这些值表示已应用某种样式的文本片段.4,9对表示用户选择的字符4,9(不包括)并单击"粗体".当用户"Unblods"时只有第一个成员每对的变为-1.因此,为了找到所有"活动"样式,我需要过滤那些带有-1的样式

我正在寻找Javascript和Clojure解决方案(因为此代码需要在浏览器端和服务器端运行).

这是一个可能的JS impl.:

styleList.map(function(curr, i) {
  if (i % 2 == 1) 
    return (styleList[i - 1] >= 0) ? curr : -1;
  else
    return -1;
}).filter(function(curr) { return curr >= 0 })
Run Code Online (Sandbox Code Playgroud)

我不喜欢这个解决方案:我传递给的函数.map()使用索引i来检查前一个值.这感觉很尴尬.我正在寻找一个更实用的解决方案.

编辑

这是另一个我不喜欢的解决方案(再次:由于arr对象的突变而不是很有用):

var arr = [];
styleList.reduce(function(prev, curr) {
  arr.push(prev == -1 ? -1 : curr);
  return curr;
});
arr.filter(function(curr, i) {
  return i % 2 == 1 && curr >= 0;
});
Run Code Online (Sandbox Code Playgroud)

编辑2

这是@CandiedOrange建议的内容(JS impl.使用下划线库):

_.zip(styleList, styleList.slice(1)).
  slice(0, -1).
  filter(function(pair, i) { return i % 2 == 0 }).
  filter(function(pair) { return pair[0] >= 0 }).
  map(function(pair) { return pair[1] })
Run Code Online (Sandbox Code Playgroud)

评论:

  • 通过组合两个.filter调用可以缩短一点.尽管如此,我认为最好将它们分开,因为它i % 2 == 0是impl的神器.而这pair[0] >= 0是所需的"真正的商业逻辑".
  • 这看起来有点冗长.我本来希望功能编程更好地处理这样的任务.在Clojure-land中有更好的解决方案吗?

编辑3

在这里困扰我的是,非功能性(命令性)解决方案非常简单:

var result = [];
styleList.forEach(function(curr, i) {
  if (i % 2 == 1 && styleList[i - 1] >= 0)
    result.push(curr);
});
Run Code Online (Sandbox Code Playgroud)

当然它不像Clojure解决方案那么简洁,但依赖于更少的构造,因此JS开发人员更有可能达到这一点,而Clojure开发人员很可能会得到Clojure解决方案(这需要熟悉->> partition first second mapfilter)

Die*_*sch 9

在Clojure中:

(->> your-list 
     (partition 2)
     (filter #(pos? (first %)))
     (map second))
Run Code Online (Sandbox Code Playgroud)

编辑:@CandiedOrange请求的解释:

  • 将您的列表分成对
  • 过滤对,只保留第一个元素为正的元素
  • 将每对转换为单个项目(第二个)