What is the most efficient way to parse a string of integers to an array?

I perform an Oraclize query on an XML file, and receive this string in return:

["31", "25", "24"]

What would be the most efficient way to parse through this string and store the numbers into a uint8 array using the minimum amount of gas?

Or is there a better way to go about this problem?
If so, please include examples.

Note:
I'm not looking to process millions of numbers this way, just around 100 or so.

• Do you want to convert array of strings to the array of integers? Or do you have this array like one string? – Dmytro Zarezenko Jun 1 '18 at 9:45
• Right. I want to extract the numbers out of this string, and put them into a uint8 array. – John DeBord Jun 1 '18 at 20:37

Since the type returned is a string, the numbers are stored in a dynamic bytes array. This means that each character occupies a single byte slot. The ASCII/UTF-8 bit representation of numbers is linearly increasing, you can parse the numbers as follows:

pragma solidity ^0.4.24;

contract NumParser {
string[] public numArray;
uint256[] public shouldBe;

constructor() public {
numArray.push("31");
numArray.push("25");
numArray.push("24");
shouldBe.push(31);
shouldBe.push(25);
shouldBe.push(24);
uint256[] memory result = parseNums(numArray);
for (uint256 i = 0; i < result.length; i++) {
assert(result[i] == shouldBe[i]);
}
}

function parseNums(string[] numsToParse) internal pure returns (uint256[]) {
uint256[] memory parsed = new uint256[](numsToParse.length);
for (uint256 i = 0; i < numsToParse.length; i++) {
bytes memory temp = bytes(numsToParse[i]);
for (uint256 j = 0; j < temp.length; j++) {
parsed[i] += (uint256(temp[j]) - 48) * (10**(temp.length - 1 - j));
}
}
return parsed;
}
}

The constructor contains a verification test that the function does indeed work correctly. The function you want to use is the parseNums function.

EDIT: You should change your original question to include that you are receiving the array in string format.

I have altered my function to work with your array as follows:

pragma solidity ^0.4.24;

contract NumParser {
string public numArray;
uint256[] private tempContainer;
uint256[] public shouldBe;

constructor() public {
numArray = "[\"31\", \"25\", \"24\"]";
shouldBe.push(31);
shouldBe.push(25);
shouldBe.push(24);
uint256[] memory result = parseNums(numArray);
tempContainer.length = 0;
for (uint256 i = 0; i < result.length; i++) {
assert(result[i] == shouldBe[i]);
}
}

function parseNums(string numsToParse) internal returns (uint256[]) {
bytes memory converted = bytes(numsToParse);
for (uint256 i = 0; i < converted.length; i++) {
if (converted[i] == 34) {
tempContainer.push(0);
uint256 j = i + 1;
for (; converted[j] != 34; j++) {
tempContainer[tempContainer.length - 1] += (uint256(converted[j]) - 48);
tempContainer[tempContainer.length - 1] *= 10;
}
tempContainer[tempContainer.length - 1] /= 10;
i = j;
}
}
return tempContainer;
}
}

Keep in mind that processing a string like this is quite costly. You also cannot use a memory array compared to the first solution because memory arrays need to have a pre-declared size while you cannot find the amount of numbers you are going to get in your array from the raw string.

This also increases the gas cost so I would advise zeroing the length as shown within the constructor to reduce the cost.

• This solves the problem of converting a string of numbers to uints. But my main problem here is taking the string ["31", "25", "24"] and extracting the numbers out of there and putting them into a uint8 array. So I guess what would need to be done to ignore the [, ], ", and , characters whilst still extracting the numbers and converting them to uint8s? – John DeBord Jun 1 '18 at 20:42
• Your question is ambiguous, you never specify that it is a string nor do you have it in escaped format i.e.: "[\"31\", \"25\", \"24\"]" I edited my answer according to your additional specifications. – Alex Papageorgiou Jun 2 '18 at 11:22