Contract-Development

映射或數組…?

  • February 6, 2020

我有一個巨大的困境!我正在開發一個智能合約,比如說Struct AStruct B。因為我想要一個檢索所有對像類型的函式AB所以我創建了一個Struct All如下所示的函式:

struct All {
  A[] a;
  B[] b;
}
struct A {...}
struct B {...}

這樣,我可以創建兩種類型的對象並將它們附加到

$$ $$每個..最後,All如果我想得到所有abAll.aAll.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.
}

您還可以(應該)實現countexists、 和keyAtIndexfor AllA以及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 ... );
}

引用自:https://ethereum.stackexchange.com/questions/79668