Javascript: 如何在多维数组上实现迭代器?
Javascript: How to implement iterator over multidimensional array?
我有 2 个 dim 数组,看起来像这样:
var a = [[1,2,3],[4,5,6],[7,8,9]];
我想写一个迭代器,当它被调用时,它会return一个值。
iterator(); //returns 1
iterator(); //returns 2
iterator(); //returns 3
我试过这样的方法:
function iterator() {
var a = [[1,2,3],[4,5,6],[7,8,9]];
var i, j;
return function() {
for (var i = 0; i < a.length; i++) {
var b = a[i];
for (var j = 0; j < b.length; j++) {
return a[i][j];
}
}
}
};
var a = iterator();
a(); //1
a(); //1
a(); //1
它总是 return 是我的第一个元素。
我可以试试这个:
function iterator() {
var a = [[1,2,3],[4,5,6],[7,8,9]];
var i = 0, j = 0;
return function() {
for (; i < a.length; i++) {
var b = a[i];
for (; j < b.length; j++) {
return a[i][j];
}
}
}
};
同样无效。
但如果我尝试这个:
function test() {
var a = [1,2,3,4,5], i = 0;
return function() {
while (i < a.length) {
return a[i++];
}
}
}
var a = test();
a(); //1
a(); //2
a(); //3
它工作正常。
这里有什么区别?如何使 for 循环工作?
对我来说另一个明显的问题是界限。当我到达数组边界时应该如何停止?
您可以使用简单的 if
来测试 j
的边界,而不是对第二个维度使用内部 for 循环
function iterator() {
var a = [[1,2,3],[4,5,6],[7,8,9]];
var i = 0, j = 0;
return function() {
for (; i < a.length; i++) {
var b = a[i];
if (j < b.length){
return a[i][j++];
}
j = 0;
}
return undefined; // reached when there is no value left
}
};
扩展标准功能通常不是一个好主意,但对于一个教学示例,我会例外。对于实际使用,我建议实现您自己的 class.
总体思路
Array.prototype.beginIterator = function()
{
var counter = 0;
return function()
{
if (counter<=this.length) return this[counter++];
else return undefined;
};
}
然后你可以像下面这样迭代:
var a = [3,1,4,1,5];
var it = a.beginIterator();
for (var i=it(); i!=undefined; i=it())
{
alert(i);
}
这目前仅适用于一维数组,但它可以与任何逻辑一起应用于其他数组或对象。
多维(任意)解:
以下迭代器允许任意组合的任意维数组:
Array.prototype.beginIterator = function()
{
var counter = 0;
var iterators = null;
return function()
{
val = undefined;
if (iterators!=null)
{
val = iterators();
if (val!==undefined) return val;
else
{
iterators = null;
counter++;
}
}
while (counter <=this.length)
{
if (!(this[counter] instanceof Array)) return this[counter++];
else
{
iterators = this[counter++].beginIterator();
val = iterators();
if (val!==undefined) return val;
}
}
return undefiend;
};
}
使用示例:
var a = [3,[3,5,7],4,[1,[2,5,8]],5];
var it = a.beginIterator();
for (var i=it(); i!=undefined; i=it())
{
alert(i);
}
为什么在这种情况下你需要一个循环。无论如何,您实际上是在展平数组。您可以在进行边界检查的同时增加索引:
function iterator() {
var a = [[1,2,3],[4,5,6],[7,8,9]], i = 0, j = 0;
return function() {
if (j >= a[i].length) { j = 0; i++; }
if (i >= a.length) { j = 0; i = 0; }
snippet.log( a[i][j++] );
}
};
var x = iterator();
x(); x(); x(); x(); x(); x(); x(); x(); x(); x();
x(); x(); x(); x(); x(); x(); x(); x(); x(); x();
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
我有 2 个 dim 数组,看起来像这样:
var a = [[1,2,3],[4,5,6],[7,8,9]];
我想写一个迭代器,当它被调用时,它会return一个值。
iterator(); //returns 1
iterator(); //returns 2
iterator(); //returns 3
我试过这样的方法:
function iterator() {
var a = [[1,2,3],[4,5,6],[7,8,9]];
var i, j;
return function() {
for (var i = 0; i < a.length; i++) {
var b = a[i];
for (var j = 0; j < b.length; j++) {
return a[i][j];
}
}
}
};
var a = iterator();
a(); //1
a(); //1
a(); //1
它总是 return 是我的第一个元素。
我可以试试这个:
function iterator() {
var a = [[1,2,3],[4,5,6],[7,8,9]];
var i = 0, j = 0;
return function() {
for (; i < a.length; i++) {
var b = a[i];
for (; j < b.length; j++) {
return a[i][j];
}
}
}
};
同样无效。
但如果我尝试这个:
function test() {
var a = [1,2,3,4,5], i = 0;
return function() {
while (i < a.length) {
return a[i++];
}
}
}
var a = test();
a(); //1
a(); //2
a(); //3
它工作正常。
这里有什么区别?如何使 for 循环工作?
对我来说另一个明显的问题是界限。当我到达数组边界时应该如何停止?
您可以使用简单的 if
来测试 j
function iterator() {
var a = [[1,2,3],[4,5,6],[7,8,9]];
var i = 0, j = 0;
return function() {
for (; i < a.length; i++) {
var b = a[i];
if (j < b.length){
return a[i][j++];
}
j = 0;
}
return undefined; // reached when there is no value left
}
};
扩展标准功能通常不是一个好主意,但对于一个教学示例,我会例外。对于实际使用,我建议实现您自己的 class.
总体思路
Array.prototype.beginIterator = function()
{
var counter = 0;
return function()
{
if (counter<=this.length) return this[counter++];
else return undefined;
};
}
然后你可以像下面这样迭代:
var a = [3,1,4,1,5];
var it = a.beginIterator();
for (var i=it(); i!=undefined; i=it())
{
alert(i);
}
这目前仅适用于一维数组,但它可以与任何逻辑一起应用于其他数组或对象。
多维(任意)解:
以下迭代器允许任意组合的任意维数组:
Array.prototype.beginIterator = function()
{
var counter = 0;
var iterators = null;
return function()
{
val = undefined;
if (iterators!=null)
{
val = iterators();
if (val!==undefined) return val;
else
{
iterators = null;
counter++;
}
}
while (counter <=this.length)
{
if (!(this[counter] instanceof Array)) return this[counter++];
else
{
iterators = this[counter++].beginIterator();
val = iterators();
if (val!==undefined) return val;
}
}
return undefiend;
};
}
使用示例:
var a = [3,[3,5,7],4,[1,[2,5,8]],5];
var it = a.beginIterator();
for (var i=it(); i!=undefined; i=it())
{
alert(i);
}
为什么在这种情况下你需要一个循环。无论如何,您实际上是在展平数组。您可以在进行边界检查的同时增加索引:
function iterator() {
var a = [[1,2,3],[4,5,6],[7,8,9]], i = 0, j = 0;
return function() {
if (j >= a[i].length) { j = 0; i++; }
if (i >= a.length) { j = 0; i = 0; }
snippet.log( a[i][j++] );
}
};
var x = iterator();
x(); x(); x(); x(); x(); x(); x(); x(); x(); x();
x(); x(); x(); x(); x(); x(); x(); x(); x(); x();
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>