Weiß jemand, wie man ein Element in einem Array löscht? Gibt es dafür eine eingebaute Methode?
Wenn nicht, weiß jemand, wie man eine solche Methode implementiert?
Verwenden Sie den delete
Operator, um das Element zu löschen:
delete array[index];
Wenn Sie keine Lücke hinterlassen möchten, müssen Sie jedes Element manuell verschieben:
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;
}
}
Wenn Ihnen die Reihenfolge egal ist, können Sie auch einfach das letzte Element in die leere Stelle kopieren und dann das letzte Element löschen.
function remove(uint[] array,uint index) returns(uint[]) {
gibt mir Error: Expression has to be an lvalue. array.length--;
auch, kann diese Methode angepasst werden, um mit Arrays aller Typen (Strukturen usw.) zu arbeiten?delete
sie in Mappings nicht wirklich sinnvoll ist.delete array[array.length-1];
ist also überflüssig. Darüber hinaus werden der Transaktion 5000 Gas hinzugefügt, da die Gasrückerstattung nur dann gilt, wenn die Speicherung von einem Wert ungleich Null auf einen Wert von Null zurückgesetzt wird. Wenn es von Null auf Null gesetzt wird (vom Compiler hinzugefügt), kostet es 5000 Benzin.Dieser Dauerbetrieb funktioniert ohne Wahrung der Ordnung:
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();
}
Um die Reihenfolge beim Abrufen aufrechtzuerhalten, ohne die Gaskosten für das Verschieben von Werten für das Recht auf Lücke zu verursachen, benötigen Sie eine zusätzliche Zuordnung zwischen dem Index jedes Elements und dem Index seines Nachfolgers, die Sie während des Einfügens und Löschens beibehalten müssen:mapping(uint => uint) private indexAfter;
Kleine Optimierung zur Antwort von 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;
}
}
Ich habe die Linie delete array[array.length-1];
vorher entfernt array.length--;
. Das macht die Funktion um 5000 Gas billiger. Der Compiler bereinigt automatisch unbelegte Slots, wenn die Array-Länge verringert wird. Das Zurücksetzen des doppelten Speichers fügt 5000 Gas hinzu.
Die meisten der vorherigen Antworten ändern direkt die Array-Länge, um ihre Länge zu reduzieren.
Seit Solidity 0.6.0 ist dies nicht mehr möglich
Der Mitgliedszugriff auf die Länge von Arrays ist jetzt immer schreibgeschützt, sogar für Speicher-Arrays. Es ist nicht mehr möglich, die Größe von Speicher-Arrays zu ändern, indem man ihrer Länge einen neuen Wert zuweist. Verwenden Sie stattdessen push(), push(value) oder pop() oder weisen Sie ein vollständiges Array zu, das natürlich vorhandene Inhalte überschreibt. Der Grund dafür ist, Speicherkollisionen durch gigantische Speicherarrays zu verhindern.
https://docs.soliditylang.org/en/v0.6.2/060-breaking-changes.html
Sie können die Antwort von medvedev1088 beheben mit:
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;
}
}
Hinweis: array.pop();
stattarray.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;
}
}
a löschen weist a den Anfangswert für den Typ zu. Dh für ganze Zahlen ist es äquivalent zu a = 0, aber es kann auch auf Arrays verwendet werden, wo es ein dynamisches Array der Länge Null oder ein statisches Array derselben Länge mit zurückgesetzten Elementen zuweist. Für Strukturen weist es eine Struktur zu, bei der alle Mitglieder zurückgesetzt werden.
> Ich habe es implementiert, vielleicht hilft es, dieses einfache Beispiel zu verstehen
**
Und wenn wir das Element mit dem Index entfernen, bleibt die Lücke nicht.
**
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;
}
}
Eine Lösung, die im Vergleich zu anderen etwas mehr Gas verbraucht.
// 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
Benutzer697