Spleißstruktureintrag nach Index in Solidität

Ich habe eine Struktur und möchte ein Element nach Index entfernen:

struct Payout {
  address addr;
  uint yield;
}

Payout[] public payouts;

Ich bin nicht mit Strukturen vertraut und eher daran gewöhnt, mit Arrays in Javascript umzugehen, wo ich so etwas tun würde:

payouts.splice(index, 1);

Was ist der beste Weg, dies mit einem Struct-Array in Solidity zu tun?

Bearbeiten: Ich möchte auch, dass das Array wie bei der Splice-Funktion nach unten verschoben wird. Wenn Sie z. B. Auszahlungen[0] löschen, werden die Daten von Auszahlungen[1] wieder an ihren Platz verschoben.

Oder Sie können ein Flag erstellen, das angibt, ob der Vertrag entfernt wurde.

Antworten (4)

Sie können einfach Folgendes tun:

function deletePayoutYield() {
    delete payout.yield;
}

Oder in einem Array:

function deletePayoutYield(uint index) {
    delete payoutArray[index].yield;
}

function deletePayout(uint index) {
    delete payoutArray[index];
}
Ich möchte sowohl yield als auch address löschen und bewirkt, dass alle anderen Einträge in ihrem Index auf einen zurückfallen. Kann ich dieses Verhalten erwarten, wenn ich 'delete payoutArray[index];' ?
Ja, ich werde die Antwort mit diesem Fall bearbeiten
Ich denke, mit dem Code, den Sie gepostet haben, werden die Daten bei payoutArray [index] gelöscht, aber das Array fällt nicht zurück. Wenn ich also payoutArray[0] lösche, bleibt es als leerer Platz ohne Daten, anstatt dass payoutArray[1] seinen Platz einnimmt.
Ich glaube nicht, dass delete das tut, was wir wollen. Das Array wird nicht reorganisiert.

Ich habe festgestellt, dass der Spleiß von Javascript leicht repliziert werden kann, indem die structs[index]Daten so eingestellt werden, dass sie den Daten des letzten Elements im Array entsprechen. Dann schneiden Sie die Länge um eins. Wenn ich das richtig verstehe, werden die Daten des letzten Elements im Array gelöscht, wenn die Länge von subtrahiert wird:

  payouts[index] = payouts[payouts.length-1];
  payouts.length = payouts.length -1;

Bearbeiten: Dies funktioniert für das, was ich brauche, aber es löst meine ursprüngliche Frage nicht wirklich, da es die Reihenfolge des Arrays nicht wie Splice beibehält. Vielleicht gibt es keine einfache Möglichkeit, ohne manuelles Durchschleifen auszukommen?

Soweit ich mich erinnern kann, werden Arrays in den meisten Sprachen als zusammenhängende Blöcke im Speicher implementiert, sodass das Spleißen eines Elements die Neuindizierung jedes Elements danach erfordern würde (im Wesentlichen eine Operation in linearer Zeit).

Wenn Sie die Reihenfolge der Liste nach dem Entfernen eines Elements beibehalten möchten, ziehen Sie die Verwendung einer verknüpften Hashmap anstelle eines Arrays in Betracht: Dies würde Ihnen einen konstanten Zugriff auf Ihre Elemente durch einen Schlüssel (nicht Index) ermöglichen, und das Entfernen wäre auch konstante Zeit (solange Sie den Schlüssel des zu entfernenden Elements kennen).

Es ist (derzeit) nicht möglich, eine zufällige Zeile aus einem geordneten Array gaseffizient zu löschen.

Es gibt zwei gängige Ansätze zur Handhabung eines logischen Löschvorgangs. Für den Fall, dass es nur wenige Löschungen gibt, kann es manchmal ausreichen, ein Flag zu setzen, das abgelaufene (entfernte) Einträge anzeigt, und sie dann logischerweise zu überspringen, wenn man die Liste durchläuft.

struct MyStruct {
  uint field1; 
  uint field2;
  bool isActive;
}

MyStruct[] public myStructs;

Dies behält die Liste in der Reihenfolge der Deklaration bei, steuert aber nicht das Wachstum der Liste.

Sie können das Wachstum der Liste steuern und auf Kosten der Listenreihenfolge eine gaseffiziente logische Löschung durchführen. Sie verschieben das letzte Element in der Liste in die Zeile, die Sie löschen möchten. Das hält die Gaskosten in jeder Größenordnung konstant.

Geben Sie hier die Bildbeschreibung ein

Um dies zu unterstützen, benötigen Sie einige Zeiger in der Datenstruktur.

Geben Sie hier die Bildbeschreibung ein

In der Praxis sollte die Ungeordnetheit der Liste in den meisten Anwendungsfällen keine Rolle spielen. Ein minimalistischer Ansatz für Smart Contracts tendiert zu Verträgen, die die Integrität der Daten sicherstellen. Der geordnete Zugriff ist normalerweise ein Anliegen, das sicher von der Smart Contract-Logik getrennt werden muss.

Eine vollständigere Anleitung mit Beispielimplementierung finden Sie hier: https://medium.com/@robhitchens/solidity-crud-part-2-ed8d8b4f74ec

Einige andere einfachere Beispiele hier: Gibt es gut gelöste und einfache Speichermuster für Solidity?