For loop in multidimensional javascript array

前端 未结 8 1470
我在风中等你
我在风中等你 2020-11-28 21:28

Since now, I\'m using this loop to iterate over the elements of an array, which works fine even if I put objects with various properties inside of it.

var cu         


        
相关标签:
8条回答
  • 2020-11-28 22:15
    var cubes = [["string", "string"], ["string", "string"]];
    
    for(var i = 0; i < cubes.length; i++) {
        for(var j = 0; j < cubes[i].length; j++) {
            console.log(cubes[i][j]);
        }
    }
    
    0 讨论(0)
  • 2020-11-28 22:16

    If you're using ES2015 and you want to define your own object that iterates like a 2-D array, you can implement the iterator protocol by:

    1. Defining an @@iterator function called Symbol.iterator which returns...
    2. ...an object with a next() function that returns...
    3. ...an object with one or two properties: an optional value with the next value (if there is one) and a boolean done which is true if we're done iterating.

    A one-dimensional array iterator function would look like this:

    // 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}
                }
            };
        };
    }
    

    Now, we can treat our Cubes object like an iterable:

    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);
    }
    

    To create our own 2-D iterable, instead of returning a value in our next() function, we can return another iterable:

    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}
            }};
        };
    }
    

    Now, we can use nested iteration:

    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);
        }
    }
    

    Note that our custom iterable won't behave like a 2-D array in all cases; for example, we haven't implemented a map() function. This answer shows how you could implement a generator map function (see here for the difference between iterators and generators; also, generators are an ES2016 feature, not ES2015, so you'll need to change your babel presets if you're compiling with babel).

    0 讨论(0)
提交回复
热议问题