[Ethereum] Creating a 2D in-memory array in Solidity

arraysmemorysolidity

I'm trying to work with 2D in-memory arrays in Solidity, in which the size is not known at compile time. I've noticed that if I define the array size as a constant, then I can use this syntax, which compiles and returns the expected 10×10 array:

uint256 constant size = 10;

function initArray() public view {
    uint256[size][size] memory arr;
    // ...
}

However, if I define the size using a variable, I get problems:

uint256 size = 10;

function initArray() public view {
    uint256[size][size] memory arr;
    // ...
}

Which leads to: TypeError: Invalid array length, expected integer literal or constant expression.

So I then try to use the new syntax, but I can't figure out how to use it for 2D arrays. First I try the simplest thing:

uint256 size = 10;

function initArray() public view {
    uint256[][] memory arr = new uint256[][](size)(size);
    // ...
}

This leads to an error: TypeError: Type is not callable, which makes sense. But then, how do I define the size of the inner arrays? I then tried:

uint256 size = 10;

function initArray() public view {
    uint256[][] memory arr = new uint256[][](size);
    for (uint i; i < size; i++) {
        arr[i] = new uint256[](size);
    }
    // ...
}

This compiles but creates some nonsense data structure. Can anyone provide some guidance? The fact that this is possible via constants leads me to think there's no fundamental barrier, I just can't figure out the syntax for passing size via a variable. Thank you!!

Best Answer

uint256 size = 10;

function initArray() public pure {
    uint256[][] memory arr = new uint256[][](size);
    for (uint i; i < size; i++) {
        arr[i] = new uint256[](size);
    }
    // ...
}

The issue in above code is you are trying to access storege variable size in pure function initArray which is not possible. You should understand the difference between view and pure function. A view function will read the storage but will not change it and a pure function does not need access to the storage and will not change it.

I tried the following code to achieve what you expect but while executing initArray function I am getting VM exception.

pragma solidity ^0.4.24;

contract Foo {
    uint256 n = 10;
    function initArray() public view  {
        uint[][] memory result = new uint[][](n*n);
        for (uint i = 0; i < n; i++){
            for(uint j = 0; j < n; j++){
                result[i][j] = 1;
            }
        }

    }
}

You can achieve the functionality of 2D arrays using a 1D array as following and it is working as expected

pragma solidity ^0.4.24;

contract Foo {
    uint256 n = 10;
    function initArray() public view  {
        uint[] memory result = new uint[](n*n);
        for (uint i = 0; i < n; i++){
           for(uint j = 0; j < n; j++){
                result[(i*9)+j]=1; 
            }
        }

    }
}

I am able to create 2D array in memory. Please refer the following code for the same :

pragma solidity ^0.4.24;

contract Foo {
    uint256 n = 10;
    function initArray(uint k,uint l) public view returns(uint)  {
        uint[][] memory arr = new uint[][](n);
        for (uint i=0; i < n; i++) {
            uint[] memory temp = new uint[](n);
            for(uint j = 0; j < n; j++){
                    temp[j]=i+j; 
                }
            arr[i] = temp;
        }
        // ...
        return arr[k][l];
    }
}

Hope it helps!