我是Javascript的新手,我正在寻找一个循环功能。这是Clojure's implementation我试图找到一个循环函数,它通过数组的值无限循环/递归。我希望在underscore库中找到类似的东西,但我找不到合适的东西。理想情况下,我想使用这样的东西:
_.head(_.cycle([1,2,3]), 100)
此函数将返回包含100个元素的数组:
[1,2,3,1,2,3,1,2,3,1,2,3,...]
我可以在Javascript中使用这样的函数吗?这是我的可行尝试,但我似乎无法让它发挥作用:
arr = [1,2,3,4,5,6,7,8,9];
var cycle = function(arr) {
arr.forEach(function(d, i) {
if (d === arr.length)
return d
d == 0
else {return d}
});
};
周期(ARR);
答案 0 :(得分:3)
您可以执行以下操作:
var cycle = function(array, count) {
var output = [];
for (var i = 0; i < count; i++) {
output.push(array[i % array.length]);
}
return output;
}
答案 1 :(得分:3)
Clojure cycle
的实现:
function cycle(input) {
return function (times) {
var i = 0, output = [];
while (i < times) {
output.push(input[i++ % input.length]);
}
return output;
};
}
用法示例:
var chars = cycle(['a', 'b']);
chars(0) // []
chars(1) // ["a"]
chars(3) // ["a", "b", "a"]
cycle([1, 2])(3) // [1, 2, 1]
Clojure take
的实现:
function take(length, input) {
return typeof input === 'function'
? input(length)
: input.slice(0, length);
}
用法示例:
take(3, [1, 2, 3, 4]) // [1, 2, 3]
take(3, cycle([1, 2])) // [1, 2, 1]
这两种实现可能都不完全符合Clojure的版本。
答案 2 :(得分:1)
尝试在JavaScript中模拟纯函数的问题是渴望:JavaScript没有惰性求值,因此您无法在JavaScript中生成无限数组。您需要在JavaScript中定义一个惰性列表。这就是我通常这样做的方式:
function cons(head, tail) {
return cont({
head: head,
tail: tail
});
}
function cont(a) {
return function (k) {
return k(a);
};
}
cons
函数类似于LISP中的cons
函数或Haskell中的:
构造函数。它需要一个元素和一个列表,并返回一个新列表,其中元素插入列表的开头。 cont
函数创建了一个延续(对于通知thunks来模拟延迟评估非常有用)。
使用cons
创建列表非常简单:
var list = cons(1, cons(2, cons(3, cons(4, cons(5, null)))));
var array = [1, 2, 3, 4, 5];
以上list
和array
是等效的。我们可以创建两个函数来将数组转换为列表,反之亦然:
function toList(array) {
var list = null, length = array.length;
while (length) list = cons(array[--length], list);
return list;
}
function toArray(list) {
var array = [];
while (list) {
list = list(id);
array = array.concat(list.head);
list = list.tail;
}
return array;
}
function id(x) {
return x;
}
现在我们有一个在JavaScript中实现惰性列表的方法,让我们创建cycle
函数:
function cycle(list) {
list = list(id);
var head = list.head;
var tail = join(list.tail, cons(head, null));
return function (k) {
return k({
head: head,
tail: cycle(tail)
});
};
}
function join(xs, ys) {
if (xs) {
xs = xs(id);
return cons(xs.head, join(xs.tail, ys));
} else return ys;
}
现在您可以按如下方式创建无限列表:
var list = cycle(toList([1,2,3]));
让我们创建一个take
函数来获取列表的前100个元素:
function take(n, xs) {
if (n > 0) {
xs = xs(id);
return cons(xs.head, take(n - 1, xs.tail));
} else return null;
}
我们现在可以轻松地获得包含[1,2,3]
重复的100个元素的数组:
var array = toArray(take(100, list));
让我们看看它是否按预期工作:http://jsfiddle.net/TR9Ma/
总而言之,JavaScript中的延迟函数式编程并不像Haskell这样的纯函数式语言那么有趣。然而,只需稍加努力就可以使它发挥作用。
答案 3 :(得分:0)
此功能应该有效。你可以在这里很好地使用mod操作。
var cycle = function(input, n) {
var output = [];
for (var i = 0; i < n; i++) {
var j = i % input.length;
output.push(input[j]);
}
return output;
}
这是一个工作小提琴:http://jsfiddle.net/K6UhS/1/
另外,我不会仅为此功能引入整个库!
答案 4 :(得分:0)
这是一个稍微紧凑的版本:
function cycle(arr, count) {
for (var i = 0, out = []; i < count; i++) {
out.push(arr[i % arr.length]);
}
return out;
}
和一个JSFiddle(将结果输出到控制台): http://jsfiddle.net/2F9hY/1/
基本上只需循环count
次,获取i % arr.length
项并将其添加到数组中。
答案 5 :(得分:0)
wu.cycle([ 1, 2, 3 ]).take(10).toArray() // [ 1, 2, 3, 1, 2, 3, 1, 2, 3, 1 ]
如果您不需要支持迭代器/流/无限列表,并且只想要一个循环遍历数组值的函数,lei-cycle提供了一个更轻量级的解决方案:
const Cycle = require('lei-cycle')
let c = Cycle([ 1, 2, 3 ])
console.log(c()) // 1
console.log(c()) // 2
console.log(c()) // 3
console.log(c()) // 1
// ...
答案 6 :(得分:0)
function cycle(array) {
let result = [...array]
result[Symbol.iterator] = function* () {
while (true)
yield* this.values()
}
return result
}