the*_*ica 14 javascript iteration lodash
在Python中将列表迭代为对(当前,下一个)的问题中,OP有兴趣将Python列表迭代为一系列current, next对.我有同样的问题,但我想用最干净的方式在JavaScript中完成,也许使用lodash.
使用简单的for循环很容易做到这一点,但它感觉不是很优雅.
for (var i = 0; i < arr.length - 1; i++) {
var currentElement = arr[i];
var nextElement = arr[i + 1];
}
Run Code Online (Sandbox Code Playgroud)
Lodash几乎可以做到这一点:
_.forEach(_.zip(arr, _.rest(arr)), function(tuple) {
var currentElement = tuple[0];
var nextElement = tuple[1];
})
Run Code Online (Sandbox Code Playgroud)
在最后一次迭代中,这nextElement将是一个微妙的问题undefined.
当然,理想的解决方案只是一个pairwise只在必要时循环的lodash功能.
_.pairwise(arr, function(current, next) {
// do stuff
});
Run Code Online (Sandbox Code Playgroud)
是否有任何现有的库已经这样做了?或者是否有另一种很好的方法在JavaScript中进行成对迭代我还没有尝试过?
澄清:如果arr = [1, 2, 3, 4],那么我的pairwise函数将迭代如下:[1, 2],[2, 3],[3, 4],不[1, 2],[3, 4].这就是OP在Python的原始问题中所要求的内容.
sal*_*ary 14
function* pairwise(iterable) {
const iterator = iterable[Symbol.iterator]();
let a = iterator.next();
if (a.done) return;
let b = iterator.next();
while (!b.done) {
yield [a.value, b.value];
a = b;
b = iterator.next();
}
}
console.log("array (0):", ...pairwise([]));
console.log("array (1):", ...pairwise(["apple"]));
console.log("array (4):", ...pairwise(["apple", "orange", "kiwi", "banana"]));
console.log("set (4):", ...pairwise(new Set(["apple", "orange", "kiwi", "banana"])));Run Code Online (Sandbox Code Playgroud)
优点:
打字稿版本(游乐场):
function* pairwise<T>(iterable: Iterable<T>): Generator<[T, T], void> {
const iterator = iterable[Symbol.iterator]();
let a = iterator.next();
if (a.done) return;
let b = iterator.next();
while (!b.done) {
yield [a.value, b.value];
a = b;
b = iterator.next();
}
}
Run Code Online (Sandbox Code Playgroud)
不知道为什么你想要这个,但你可以在一个函数上做出"丑陋"的部分,然后它看起来不错:
arr = [1, 2, 3, 4];
function pairwise(arr, func){
for(var i=0; i < arr.length - 1; i++){
func(arr[i], arr[i + 1])
}
}
pairwise(arr, function(current, next){
console.log(current, next)
})
Run Code Online (Sandbox Code Playgroud)
您甚至可以稍微修改它以便能够迭代所有i,i + n对,而不仅仅是下一个:
function pairwise(arr, func, skips){
skips = skips || 1;
for(var i=0; i < arr.length - skips; i++){
func(arr[i], arr[i + skips])
}
}
pairwise([1, 2, 3, 4, 5, 6, 7], function(current,next){
console.log(current, next) // displays (1, 3), (2, 4), (3, 5) , (4, 6), (5, 7)
}, 2)
Run Code Online (Sandbox Code Playgroud)
在Ruby中,这称为each_cons:
(1..5).each_cons(2).to_a # => [[1, 2], [2, 3], [3, 4], [4, 5]]
Run Code Online (Sandbox Code Playgroud)
它是为Lodash提出的,但被拒绝了。但是,npm上有一个each-cons模块:
const eachCons = require('each-cons')
eachCons([1, 2, 3, 4, 5], 2) // [[1, 2], [2, 3], [3, 4], [4, 5]]
Run Code Online (Sandbox Code Playgroud)
Ramda中还有一个aperture函数可以执行相同的操作:
const R = require('ramda')
R.aperture(2, [1, 2, 3, 4, 5]) // [[1, 2], [2, 3], [3, 4], [4, 5]]
Run Code Online (Sandbox Code Playgroud)
d3.js提供了在某些语言中称为 a 的内置sliding版本:
console.log(d3.pairs([1, 2, 3, 4])); // [[1, 2], [2, 3], [3, 4]]Run Code Online (Sandbox Code Playgroud)
<script src="http://d3js.org/d3.v5.min.js"></script>Run Code Online (Sandbox Code Playgroud)
# d3.pairs(数组[, 减速器]) <>
对于指定数组中的每个相邻元素对,按顺序调用指定的缩减器函数,传递元素 i 和元素 i - 1。如果未指定缩减器,则默认为为每个元素创建一个二元素数组的函数一对。
这个答案的灵感来自我在 Haskell 中看到的类似问题的答案:https : //stackoverflow.com/a/4506000/5932012
我们可以使用 Lodash 的 helpers 来编写以下内容:
const zipAdjacent = function<T> (ts: T[]): [T, T][] {
return zip(dropRight(ts, 1), tail(ts));
};
zipAdjacent([1,2,3,4]); // => [[1,2], [2,3], [3,4]]
Run Code Online (Sandbox Code Playgroud)
(与 Haskell 的等价物不同,我们需要,dropRight因为 Lodash 的zip行为与 Haskell的不同:它将使用最长数组的长度而不是最短数组的长度。)
在 Ramda 中也是如此:
const zipAdjacent = function<T> (ts: T[]): [T, T][] {
return R.zip(ts, R.tail(ts));
};
zipAdjacent([1,2,3,4]); // => [[1,2], [2,3], [3,4]]
Run Code Online (Sandbox Code Playgroud)
虽然 Ramda 已经有一个函数来覆盖这个叫做孔径。这稍微更通用,因为它允许您定义所需的连续元素数量,而不是默认为 2:
R.aperture(2, [1,2,3,4]); // => [[1,2], [2,3], [3,4]]
R.aperture(3, [1,2,3,4]); // => [[1,2,3],[2,3,4]]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8648 次 |
| 最近记录: |