Solidity In-Memory Array – How to Fill Dynamic In-Memory Arrays

arraysmemoryremixsoliditystorage

For some reason solidity doesn't allow to push values into memory array

Member "push" is not available in bytes32[] memory outside of
storage.

Here is sample contract code:

pragma solidity ^0.4.21;

contract Foo {
    function getRange(uint n) public pure returns(uint[]) {
        uint[] memory result;
        for (uint i = 0; i < n; i++)
            if (someCondition(i))
               result.push(i);
        return result;
    }
}

I could allocate maximum possible array of size n and then shrink it, but it may hurt performance (n could be in order of magnitude of 100000 while final length of result is 0..100). For example, someCondition could be isPrime. In this case we have large N (which makes impossible to preallocate an array) and small list of resulting prime numbers.

How could it be done?


I ended up with preallicating array of size n and then shrinking it once I know it's final length:

function getRange(uint n) public pure returns(uint[]) {
    uint tookCount = 0;
    uint[] memory result = new uint[](n);
    for (uint i = 0; i < n; i++)
        if (someCondition(i)) {
            result.push(i);
            tookCount++;
        }

    uint[] memory trimmedResult = new uint[](tookCount);
    for (uint j = 0; j < trimmedResult.length; j++) {
        trimmedResult[j] = result[j];
    }
    return trimmedResult;
}

Best Answer

Dynamic arrays are only available in storage, not in memory. In your case, the size of the result array is known upfront (n). So, you can just declare an array with length of n. Then you can fill it up using i, which goes from 0 to n - 1

pragma solidity ^0.4.21;

contract Foo {
    function getRange(uint n) public pure returns(uint[]) {
        uint[] memory result = new uint[](n);
        for (uint i = 0; i < n; i++)
            result[i] = i;
        return result;
    }
}
Related Topic