用于根据上一个值筛选序列的惯用clojure和Javascript表达式
Idiomatic clojure and Javascript expression for filtering a sequence based on the previous value
所以我有一个整数序列。我想选择其他所有元素,但前提是它前面的元素是正的。例如,给定以下输入:
4, 9, -1, 8, 3, 20, -1, 7
我想得到这个输出:
9, 20
(上下文:这些值表示应用了特定样式的文本段。4,9对表示用户选择的字符4,9(不包括)并单击"粗体"。当用户"取消绑定"时,每对中只有第一个成员变为-1。因此,为了找到所有"活动"样式,我需要过滤那些带有-1 out)的样式
我正在寻找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 })
我不喜欢这个解决方案:我传递给.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;
});
编辑2
以下是@CandidOrange的建议(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] })
评论:
- 这可以通过组合两个CCD_ 4调用来缩短一点。不过,我认为最好将它们分开,因为
i % 2 == 0
是impl的工件。而CCD_ 6是这里所需要的"真正的业务逻辑" - 这看起来有点冗长。我希望函数式编程能更好地处理这样的任务。在Clojure的土地上有更好的解决方案吗
编辑3
这里困扰我的是,非功能(命令式)解决方案非常琐碎:
var result = [];
styleList.forEach(function(curr, i) {
if (i % 2 == 1 && styleList[i - 1] >= 0)
result.push(curr);
});
当然,它不像Clojure解决方案那样简洁,但依赖于更少的构造,因此JS开发人员比Clojure开发人员更有可能实现这一点(需要熟悉->>
partition
first
second
map
和filter
)
在Clojure:中
(->> your-list
(partition 2)
(filter #(pos? (first %)))
(map second))
编辑:根据@CandidOrange:的要求进行解释
- 将列表分成两组
- 过滤配对,只保留第一个元素为正的配对
- 将每一对转换为单个项目(第二个)
最简单的解决方案
var array=[4, 9, -1, 8, 3, 20, -17];
var s;
for(var i=0; i < array.length ; i+=2) {
if(array[i] < 0 || array[i+1]<0){
continue;
} else {
if(!s) {
s=array[i+1];
} else {
s=s+","+array[i+1];
}
}
}
alert(s);
使用undercore.js:
var styleList = [4, 9, -1, 8, 3, 20, -1, 7];
var pairs = _.zip(_.filter(styleList, function(val, idx) { return idx % 2 == 0; }),
_.filter(styleList, function(val, idx) { return idx % 2 == 1; }));
_.chain(pairs)
.filter(function (pair) { return pair[0] >= 0; })
.map(function (pair) { return pair[1]; })
.value();
pairs
仅包含您感兴趣的对:[[4,9],[-1,8],[3,20],[-1,7]]
。chain
函数类似于Clojure中的->
线程宏。CCD_ 17保持第一元素大于或等于零的对。并且CCD_ 18正在返回该对中的第二个元素。CCD_ 19提取CCD_。
Michael Fogus有一本关于函数式JavaScript的好书:函数式JavaScript:使用Undercore.js 介绍函数式编程
对于Javascript解决方案来说,可能是这样的。它似乎解决了您对Javascript解决方案的反感。
function checkObjectCoercible(inputArg) {
var type = typeof inputArg;
if (type === 'undefined' || inputArg === null) {
throw new TypeError('Cannot convert argument to object');
}
return inputArg;
}
Object.defineProperty(Number, 'isPositive', {
value: function (value) {
if (typeof value !== 'number') {
return false;
}
return value === 0 ? (1 / value) === Infinity : value > 0;
}
});
Object.defineProperty(Array.prototype, 'groupsOf', {
value: function (num) {
var object = Object(checkObjectCoercible(this)),
length = object.length,
count = num >>> 0,
newList = [],
index,
group,
idx;
if (length && count) {
for (idx = 0; idx < length; idx += count) {
group = [];
group.length = count;
for (index = 0; index < count; index += 1) {
group[index] = object[idx + index];
}
newList.push(group);
}
}
return newList;
}
});
var styleList = [4, 9, -1, 8, 3, 20, -1, 7],
out = styleList.groupsOf(2).filter(function (pair) {
return Number.isPositive(pair[0]) && typeof pair[1] === 'number';
}).map(function (pair) {
return pair[1];
});
document.getElementById('out').textContent = JSON.stringify(out, null, 2);
<pre id="out"></pre>
这些解决方案考虑了稀疏阵列和CCD_ 21的可能使用。它们还处理可能存在奇数个元素的情况。
还有一种可能性。
function checkObjectCoercible(inputArg) {
var type = typeof inputArg;
if (type === 'undefined' || inputArg === null) {
throw new TypeError('Cannot convert argument to object');
}
return inputArg;
}
Object.defineProperty(Number, 'isPositive', {
value: function (value) {
if (typeof value !== 'number') {
return false;
}
if (value === 0) {
return (1 / value) === Infinity;
}
return value > 0;
}
});
function pairByIndex(acc, item, index) {
var key = Math.floor(index / 2);
if (!acc[key]) {
acc[key] = [item];
acc[key].length = 2;
} else {
acc[key][1] = item;
}
return acc;
}
Object.defineProperty(Array.prototype, 'toPairs', {
value: function () {
return checkObjectCoercible(this).reduce(pairByIndex, []);
}
});
function firstEntry(pair) {
return pair[0];
}
function secondEntry(pair) {
return pair[1];
}
function firstEntryIsPositive(pair) {
return Number.isPositive(firstEntry(pair));
}
var styleList = [4, 9, -1, 8, 3, 20, -1, 7],
out = styleList.toPairs().filter(firstEntryIsPositive).map(secondEntry);
document.getElementById('out').textContent = JSON.stringify(out, null, 2);
<pre id="out"></pre>
- java.net和javascript之间正则表达式的差异
- Grunt匹配正则表达式
- 不同浏览器中的空白字符正则表达式行为
- ng init中的表达式无法使用ng repeat
- 正则表达式在字符串中找到base64
- 我的AngularJS表达式没有'不起作用
- 子字符串/正则表达式以获取字符串中保存的 SRC 值
- 调用正则表达式匹配的函数
- 表达式引擎扩展开发-向呈现的条目添加自定义javascript
- 使用正则表达式评估电子邮件地址时出现性能问题
- Javascript 正则表达式 : ^[^/s/]+[a-z]{1,}[0-9]*[-_]*[^/][
- JavaScript正则表达式文本与RegExp对象
- 正则表达式只允许 x 个整数
- 使用正则表达式将输入格式设置为单字符逗号、单字符逗号等
- 改进用于验证付款金额的正则表达式
- 正则表达式与数字中的第二个点匹配
- 键按正则表达式以查找具有负值的小数
- 一个正则表达式,用于从JS中的HTML标记中删除id、样式和类属性
- "锻造;React中的表达式
- 用于根据上一个值筛选序列的惯用clojure和Javascript表达式