Realizo una consulta de Oracle en un archivo XML y recibo esta cadena a cambio:
["31", "25", "24"]
¿Cuál sería la forma más eficiente de analizar esta cadena y almacenar los números en una uint8
matriz utilizando la cantidad mínima de gas?
¿O hay una mejor manera de abordar este problema?
Si es así, incluya ejemplos.
Nota:
No busco procesar millones de números de esta manera, solo alrededor de 100 más o menos.
Dado que el tipo devuelto es a string
, los números se almacenan en una bytes
matriz dinámica. Esto significa que cada personaje ocupa un solo byte
espacio . La representación de números ASCII/UTF-8 bits aumenta linealmente, puede analizar los números de la siguiente manera:
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;
}
}
El constructor
contiene una prueba de verificación de que la función funciona correctamente. La función que desea utilizar es la parseNums
función .
EDITAR: debe cambiar su pregunta original para incluir que está recibiendo la matriz en string
formato .
He modificado mi función para trabajar con su matriz de la siguiente manera:
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;
}
}
Tenga en cuenta que procesar una solicitud string
como esta es bastante costoso. Tampoco puede usar una memory
matriz en comparación con la primera solución porque las memory
matrices deben tener un tamaño predeclarado, mientras que no puede encontrar la cantidad de números que obtendrá en su matriz a partir de la cadena sin procesar.
Esto también aumenta el costo del gas, por lo que recomendaría poner a cero la longitud como se muestra en el constructor
para reducir el costo.
["31", "25", "24"]
y extraer los números de allí y ponerlos en una uint8
matriz. Entonces, supongo, ¿qué habría que hacer para ignorar los caracteres [
, ]
, "
y ,
mientras se siguen extrayendo los números y convirtiéndolos en uint8
s?string
ni la tiene en formato de escape, es decir: "[\"31\", \"25\", \"24\"]"
edité mi respuesta de acuerdo con sus especificaciones adicionales.
Dmitro Zarezenko
Juan De Bord
uint8
matriz.