映射或數組…?
我有一個巨大的困境!我正在開發一個智能合約,比如說
Struct A
和Struct B
。因為我想要一個檢索所有對像類型的函式A
,B
所以我創建了一個Struct All
如下所示的函式:struct All { A[] a; B[] b; } struct A {...} struct B {...}
這樣,我可以創建兩種類型的對象並將它們附加到
$$ $$每個..最後,
All
如果我想得到所有a
和b
或All.a
或All.b
如果方便,我會返回。到現在為止還挺好。雖然,現在在刪除和編輯方面要困難得多,我必須遍歷所有數組並刪除或更改我想要的數組,並轉移或其他需要的東西。所以我想,好吧,地圖更容易做到這一點。但另一方面,使用地圖,我不能只檢索兩個結構的全部內容。 我知道這不是一個直接的問題,而是尋求幫助,希望有人遇到過同樣的情況或知道如何處理這種契約設計困境。基本上,我希望能夠檢索我可能擁有的所有不同類型的結構,但也希望能夠編輯它們所在的池。有什麼建議嗎?
這有點進退兩難。您需要用於隨機訪問的映射和用於迭代的數組。您應該不惜一切代價避免循環,因為 O(1) 複雜性因此契約可以擴展。
這個庫有助於集合上的 CRUD 操作,包括 delete。這裡有一個快速解釋器式的演練,帶有返回到詳細教程的連結,該教程解釋了它是如何工作的以及為什麼它應該以這種方式工作。後者可能是最好的起點,因為它準確地關注您正在尋找的困境以及如何解決它。庫實現(更新)是對原理的程式碼更新和細化。
pragma solidity 0.5.16; import "./HitchensUnorderedKeySet.sol"; contract AB { using HitchensUnorderedKeySetLib for HitchensUnorderedKeySetLib.Set; struct A { uint arg1; uint arg2; } struct B { uint arg1; uint arg2; } struct All { HitchensUnorderedKeySetLib.Set aSet; HitchensUnorderedKeySetLib.Set bSet; mapping(bytes32 => A) aStructs; mapping(bytes32 => B) bStructs; } HitchensUnorderedKeySetLib.Set allSet; mapping(bytes32 => All) allStructs;
^^^ 那是你的佈局。
// Now, CRUD ops function newAll(bytes32 key) public { allSet.insert(key); } function delAll(bytes32 key) public { All storage a = allStructs[key]; require(a.aSet.count() == 0, "Remove A elements first."); // optional cleanup requirements require(a.bSet.count() == 0, "Remove B elements first."); delete allStructs[key]; allSet.remove(key); } function appendASet(bytes32 allKey, bytes32 aKey, uint arg1, uint arg2) public { All storage a = allStructs[allKey]; require(allSet.exists(allKey), "allKey does not exist."); a.aSet.insert(aKey); A storage aa = a.aStructs[aKey]; aa.arg1 = arg1; aa.arg2 = arg2; } // carry on with appendB, delete A and delete B. }
您還可以(應該)實現
count
、exists
、 和keyAtIndex
forAll
,A
以及B
整個結構的完整 CRUD 實現。count()
和keyAtIndex()
函式讓客戶端一次迭代一個元素的列表,這是理想的,因為操作以任何規模的固定 gas 成本完成(客戶端可以迭代,因此合約不必這樣做)。在嵌套結構的情況下,公開一些計數資訊可能會很好:
function getAllStruct(bytes32 key) public returns (uint countA, uint countB) { All storage a = allStructs[key]; return(a.aSet.count(), a.bSet.count(), members ... ); }