Javascript中的循环功能

时间:2014-01-29 18:07:33

标签: javascript

我是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);

7 个答案:

答案 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];

以上listarray是等效的。我们可以创建两个函数来将数组转换为列表,反之亦然:

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函数,可以执行此操作:

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
}