Si vous utilisez ES2015 et que vous voulez définir votre propre objet qui itère comme un tableau 2-D, vous pouvez mettre en œuvre le iterator protocol par:
- Définition d'une fonction @@ iterator appelé
Symbol.iterator
qui retourne ...
- ... un objet avec une fonction qui retourne
next()
...
- ... un objet avec un ou deux propriétés: un
value
en option avec la valeur suivante (si elle existe) et un booléen done
ce qui est vrai si nous avons fini d'itérer.
Une unidimensionnelle fonction iterator tableau ressemblerait à ceci:
// our custom Cubes object which implements the iterable protocol
function Cubes() {
this.cubes = [1, 2, 3, 4];
this.numVals = this.cubes.length;
// assign a function to the property Symbol.iterator
// which is a special property that the spread operator
// and for..of construct both search for
this[Symbol.iterator] = function() { // can't take args
var index = -1; // keep an internal count of our index
var self = this; // access vars/methods in object scope
// the @@iterator method must return an object
// with a "next()" property, which will be called
// implicitly to get the next value
return {
// next() must return an object with a "done"
// (and optionally also a "value") property
next: function() {
index++;
// if there's still some values, return next one
if (index < self.numVals) {
return {
value: self.cubes[index],
done: false
};
}
// else there's no more values left, so we're done
// IF YOU FORGET THIS YOU WILL LOOP FOREVER!
return {done: true}
}
};
};
}
Maintenant, nous pouvons traiter notre objet Cubes
comme un itérable:
var cube = new Cubes(); // construct our cube object
// both call Symbol.iterator function implicitly:
console.log([...cube]); // spread operator
for (var value of cube) { // for..of construct
console.log(value);
}
Pour créer le vôtre 2-D itératives, au lieu de retourner une valeur dans notre fonction next()
, nous pouvons retourner une autre itérables:
function Cubes() {
this.cubes = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
];
this.numRows = this.cubes.length;
this.numCols = this.cubes[0].length; // assumes all rows have same length
this[Symbol.iterator] = function() {
var row = -1;
var self = this;
// create a closure that returns an iterator
// on the captured row index
function createColIterator(currentRow) {
var col = -1;
var colIterator = {}
// column iterator implements iterable protocol
colIterator[Symbol.iterator] = function() {
return {next: function() {
col++;
if (col < self.numCols) {
// return raw value
return {
value: self.cubes[currentRow][col],
done: false
};
}
return {done: true};
}};
}
return colIterator;
}
return {next: function() {
row++;
if (row < self.numRows) {
// instead of a value, return another iterator
return {
value: createColIterator(row),
done: false
};
}
return {done: true}
}};
};
}
Maintenant, nous pouvons utiliser l'itération imbriquée:
var cube = new Cubes();
// spread operator returns list of iterators,
// each of which can be spread to get values
var rows = [...cube];
console.log([...rows[0]]);
console.log([...rows[1]]);
console.log([...rows[2]]);
// use map to apply spread operator to each iterable
console.log([...cube].map(function(iterator) {
return [...iterator];
}));
for (var row of cube) {
for (var value of row) {
console.log(value);
}
}
Notez que notre coutume itérables ne se comportera pas comme un tableau 2D dans tous les cas; par exemple, nous n'avons pas implémenté une fonction map()
. This answer montre comment vous pouvez implémenter une fonction de génération de générateur (see here pour la différence entre les itérateurs et les générateurs, ainsi que les générateurs sont une fonctionnalité ES2016, pas ES2015, donc vous aurez besoin de change your babel presets si vous compilez avec babel).
Votre solution fonctionne uniquement avec les baies 2D, mais j'ai trouvé un moyen de faire une boucle sur les baies avec un nombre quelconque de dimensions: http://stackoverflow.com/a/15854485/975097 –
@AndersonGreen OP recherchait spécifiquement Tableaux 2D, donc la réponse ci-dessus. Merci pour le lien - espérons que cela aidera quelqu'un à la recherche d'une solution similaire dans le futur! –
Salut, comment obtenir le résultat comme «1,4,7», «1,4,8», «1,4,9», «1,5,7», «1,5,8» ... – Bharadwaj