40 votes

Itération avec la boucle while au lieu de la boucle for

ECMAScript 6 présente les générateurs, les itérateurs de la syntaxe et de sucre pour l'itération. Node.JS v0.11.4 avec les drapeaux

--harmony --use_strict --harmony_generators

comprend les éléments suivants générateur

function* fibonacci() {
  let previous = 0;
  let current = 1;

  while(true) {
    let temp = previous;
    previous = current;
    yield current = temp + current;
  }
}

Je peux ensuite imprimer les nombres de Fibonacci à moins de 1000.

for(let value of fibonacci()) {
    if(value > 1000) { break; }
    console.log(value);
}

Pour cet exemple, une while boucle au lieu d'un for boucle serait plus naturel, similaire à

while(value of fibonacci() < 1000) {
    console.log(value);
}

Peut itération de itérateurs être fait avec un while boucle au lieu d'un for boucle?

13voto

fsw Points 2078

Est-ce que quelque chose comme ça vous satisferait?

 var sequence = fibonacci();
var value;
while ((value = sequence.next()) < 1000) {
    console.log(value);
}
 

de plus, peut-être même une solution plus intéressante serait quelque chose comme:

 function* fibonacci(limit){
  let previous = 0;
  let current = 1;

  while(previous + current < limit) {
    let temp = previous;
    previous = current;
    yield current = temp + current;
  }
}

for(let value of fibonacci(1000)) {
    console.log(value);
}
 

7voto

Benjamin Gruenbaum Points 51406

Il y a deux façons, j'irais sur le sujet, étant donné que d'autres langages qui prennent en charge ce problème:

1) à l'aide de l'Harmonie des procurations, qui vous permettrait de faire de la méta-tables (un peu comme dans lua) et de permettre un paresseux iterables. Ceci permettrait à l'notation suivante:

var arr = ...; // create the resource
for(var i=0;arr[i]<1000;i++){
    arr[i]; // consume fibonacci numbers
}

2) La seconde à l'aide d'un take de la fonction vous permettant de consommer un objet iterable avec .forEach comme en C# ou python. Ce qui permettrait à la notation suivante:

 takeWhile(fibGenerator,(item) => item<1000).forEach(... // consume with predicate

Première approche à l'aide de l'harmonie des procurations

Remarque... for of boucles à travers les objets. Il ne garantit pas l'ordre à tous. Vous pouvez cependant faire quelque chose comme ce qui suit pour obtenir la notion d'un paresseux itérer.

Vous avez à courir nœud à la fois avec l' --harmony_generators et --harmony_proxies drapeaux:

var arr = ...; // create an array and proxy it, use a generator internally
arr[50]; // will calculate the 50th fibonacci element and return it.
arr[100];// will calculate the 100th fibonacci element and return it.
for(var i=0;arr[i]<1000;i++){
   arr[i];//the i-th fibonacci number
}

Il ne calculer les nombres a pas encore récupéré, ce qui vous permettra d'utiliser un simple for boucle.

Voici comment*:

var cache = [];
var handler = {
        get: (function(){
          function fibIterator(){
             var t=0,a=0,b=0;
             return function(){
                t=a;
                a+=b;
                b=t;
                return a;
             }
          }
          var iterator = fibIterator();
          return function (target, fibNumber) {
                if (name in cache) {
                    return cache[name];
                }
                while(iterator < fibNumber){
                    // update indexes. 
                }
           })()
        }
    };
var arr = Proxy.create(handler);

(Juste ne pas s'attendre à être très rapide)

*(à l'aide de vieux proxy notation, puisque la nouvelle n'est pas pris en charge dans le nœud pourtant, sera mise à jour une fois qu'il obtient l'appui)


Note de côté, en JavaScript depuis peut avoir les fonctions internes de l'état par le biais de fermetures, vous n'avez même pas vraiment besoin d'un générateur

La deuxième approche, à l'aide d'un itérateur Take fonction.

C'est ce que vous auriez normalement faire dans des langages tels que C# pour ce cas d'utilisation.

function takeWhile(generating, predicate){
    var res = [],last;
    do{
        res.push(last=generating())
    }while(predicate(last));
    return res;
} 

Puis faire quelque chose comme

var res = takeWhile(fibIterator,function(item){
    return item<1000;
});
res.forEach(function(){ ...

Ou par compte:

function take(generating,numToTake){
    var res = [],num;
    do{
        res.push(last=generating())
    }while(num++ < numToTake);
    return res;
}

var res = take(fibIterator,1000);//first 1000 numbers

0voto

Mattias Buelens Points 7690

Oui, il est possible de le faire en utilisant les méthodes classiques du générateur.

 var fib = fibonacci(), value;
while( (value = fib.next()) < 1000 ) {
    console.log(value);
}
 

Bien que je semble préférer l’énoncé for...of qui se charge de gérer les prochains appels et de traiter avec StopIteration (si la séquence est finie).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X