所以我有一个整数序列。我想选择所有其他元素,但前提是它前面的元素是正数。例如,给定此输入:
4, 9, -1, 8, 3, 20, -1, 7
我想得到这个输出:
9, 20
(上下文:这些值表示已应用某种样式的文本片段.4,9对表示用户选择的字符4,9(不包括)并单击“Bold”。当用户“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 })
我不喜欢这个解决方案:我传递给.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
这是@CandiedOrange建议的内容(JS impl。使用underscore库):
_.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] })
评论:
.filter
调用可以缩短一点。尽管如此,我认为最好将它们分开,因为i % 2 == 0
是impl的工件。而pair[0] >= 0
是这里所需的“真正的商业逻辑”。编辑3
困扰我的是,非功能性(命令式)解决方案非常简单:
var result = [];
styleList.forEach(function(curr, i) {
if (i % 2 == 1 && styleList[i - 1] >= 0)
result.push(curr);
});
当然它不像Clojure解决方案那么简洁,但依赖于更少的构造,因此JS开发人员更有可能达到这个目的,而Clojure开发人员很可能会得到Clojure解决方案(需要熟悉->>
partition
first
second
map
和filter
)
答案 0 :(得分:9)
在Clojure中:
(->> your-list
(partition 2)
(filter #(pos? (first %)))
(map second))
编辑:@CandiedOrange请求的解释:
答案 1 :(得分:0)
最简单的解决方案
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);
答案 2 :(得分:0)
对于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);
&#13;
<pre id="out"></pre>
&#13;
这些解决方案考虑了稀疏数组和-0
的可能用途。它们还处理可能存在奇数个元素的情况。
另一种可能性。
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);
&#13;
<pre id="out"></pre>
&#13;
答案 3 :(得分:0)
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中的->
线程宏。 filter
保持第一个元素大于或等于零的对。并且map
返回该对的第二个元素。 value
提取chain
的值。
Michael Fogus有一本关于功能性JavaScript的好书:Functional JavaScript: Introducing Functional Programming with Underscore.js