¿Alguien sabe cómo eliminar un elemento en una matriz? ¿Hay algún método incorporado para hacer eso?
Si no, ¿alguien sabe cómo implementar dicho método?
Utilice el delete
operador para eliminar el elemento:
delete array[index];
Si no desea dejar un espacio, debe mover cada elemento manualmente:
contract test{
uint[] array = [1,2,3,4,5];
function remove(uint index) returns(uint[]) {
if (index >= array.length) return;
for (uint i = index; i<array.length-1; i++){
array[i] = array[i+1];
}
delete array[array.length-1];
array.length--;
return array;
}
}
Si no le importa el orden, también puede simplemente copiar el último elemento en el lugar vacío y luego eliminar el último elemento.
function remove(uint[] array,uint index) returns(uint[]) {
me da". Error: Expression has to be an lvalue. array.length--;
Además, ¿ese método se puede adaptar para trabajar en matrices de todo tipo (struct, etc.)?delete
que en realidad no tiene sentido en las asignaciones.delete array[array.length-1];
es redundante. Además, agrega 5000 de gas a la transacción, ya que el reembolso de gas se aplica solo en el caso de que el almacenamiento se restablezca de un valor distinto de cero a cero. Si está configurado de cero a cero (agregado por el compilador), cuesta 5000 de gasolina.Esta operación constante funciona sin conservar el orden:
uint[] internal array;
// Move the last element to the deleted spot.
// Remove the last element.
function _burn(uint index) internal {
require(index < array.length);
array[index] = array[array.length-1];
array.pop();
}
Para conservar el orden en la recuperación sin incurrir en el costo de gas de cambiar los valores de derecho de brecha, necesitará una asignación adicional entre el índice de cada elemento y el índice de su sucesor que debe mantener durante la inserción y eliminación:mapping(uint => uint) private indexAfter;
Pequeña optimización de la respuesta de Tjaden Hess:
contract Test {
uint[] array = [1,2,3,4,5];
function remove(uint index) returns(uint[]) {
if (index >= array.length) return;
for (uint i = index; i<array.length-1; i++){
array[i] = array[i+1];
}
array.length--;
return array;
}
}
Quité la línea delete array[array.length-1];
antes array.length--;
. Esto abarata la función por 5000 de gas. El compilador limpiará automáticamente las ranuras desocupadas cuando se reduzca la longitud de la matriz. El restablecimiento de almacenamiento doble agrega 5000 de gas.
La mayoría de las respuestas anteriores modifican directamente la longitud de la matriz para reducir su longitud.
Desde Solidity 0.6.0 esto ya no es posible
El acceso de los miembros a la longitud de los arreglos ahora es siempre de solo lectura, incluso para los arreglos de almacenamiento. Ya no es posible cambiar el tamaño de los arreglos de almacenamiento asignando un nuevo valor a su longitud. Use push(), push(value) o pop() en su lugar, o asigne una matriz completa, que por supuesto sobrescribirá el contenido existente. La razón detrás de esto es evitar colisiones de almacenamiento por matrices de almacenamiento gigantes.
https://docs.soliditylang.org/en/v0.6.2/060-breaking-changes.html
Puede corregir la respuesta de medvedev1088 con:
contract Test {
uint[] array = [1,2,3,4,5];
function remove(uint index) returns(uint[]) {
if (index >= array.length) return;
for (uint i = index; i<array.length-1; i++){
array[i] = array[i+1];
}
array.pop();
return array;
}
}
Aviso: array.pop();
en lugar dearray.length--;
pragma solidity ^0.4.11;
contract TestArray {
uint[] public original;
uint[] public newOr;
event Log(uint n, uint a, uint b, uint c);
function TestArray(){
original.push(1);
original.push(2);
original.push(3);
original.push(4);
}
function test(){
newOr = remove(original, 1);
Log(newOr.length, newOr[0], newOr[1], newOr[2]);
}
function remove(uint[] array, uint index) internal returns(uint[] value) {
if (index >= array.length) return;
uint[] memory arrayNew = new uint[](array.length-1);
for (uint i = 0; i<arrayNew.length; i++){
if(i != index && i<index){
arrayNew[i] = array[i];
} else {
arrayNew[i] = array[i+1];
}
}
delete array;
return arrayNew;
}
}
delete a asigna el valor inicial del tipo a a. Es decir, para números enteros es equivalente a a = 0, pero también se puede usar en arreglos, donde asigna un arreglo dinámico de longitud cero o un arreglo estático de la misma longitud con todos los elementos reiniciados. Para estructuras, asigna una estructura con todos los miembros reiniciados.
> Lo he implementado, puede ser útil entenderlo con este simple ejemplo
**
Y si eliminamos el elemento usando el índice, no dejará el espacio.
**
http://solidity.readthedocs.io/en/v0.4.21/types.html
contract UserRecord {
constructor() public { owner = msg.sender; }
address owner;
modifier onlyOwner {
require(msg.sender == owner);
_;
}
struct User {
bytes32 userEmail;
uint index;
}
mapping (bytes32 => User) private users;
bytes32[] private usersRecords;
event LogNewUser(bytes32 indexed userEmail, uint index);
function setUseremail(bytes32 _userEmail) public onlyOwner returns(bool success){
users[_userEmail].userEmail = _userEmail;
users[_userEmail].index = usersRecords.push(_userEmail) -1;
emit LogNewUser(
_userEmail,
users[_userEmail].index
);
return true;
}
//this will delete the user at particular index and gap will be not there
function deleteUser(bytes32 _userEmail) public onlyOwner returns(uint index){
require(!isUser(_userEmail));
uint toDelete = users[_userEmail].index;
bytes32 lastIndex = usersRecords[usersRecords.length-1];
usersRecords[toDelete] = lastIndex;
users[lastIndex].index = toDelete;
usersRecords.length--;
return toDelete;
}
}
Una solución que consume un poco más de gas en comparación con otras.
// Preload any custom data through other functions
address[] customArray;
function removeIndex(uint256 index) external {
address[] storage _array = customArray;
_array.push(_array[index]);
for (uint i=index; i<_array.length-1; i++){
_array[i] = _array[i+1];
}
_array.pop();
_array.pop();
customArray = _array;
}
tjaden hess
usuario697