Solidity

將數組中每個結構的主鍵映射到他們自己

  • May 5, 2019
pragma solidity ^0.4.17;
contract Campaign{
   struct Transaction {
       address Creditor;
       uint Amount;
   }
   Transaction[] public Transactionss;
   mapping(address => Transaction) public TransactionsMap;

   function addTransaction(address _address,uint _amount) public {

       Transaction memory newRequest = Transaction({
          Creditor: _address,
          Amount: _amount });
       Transactionss.push(newRequest); 
       TransactionsMap[_address]=Transactionss[Transactionss.length-1];


   }
   function Testing()public {
       addTransaction(0xaef0B7Edd5D2E9315027ADFA4642E16a5c85Afd8,100);
       TransactionsMap[0xaef0B7Edd5D2E9315027ADFA4642E16a5c85Afd8].Amount++;
   }


   function a()public view  returns (uint){
       return TransactionsMap[0xaef0B7Edd5D2E9315027ADFA4642E16a5c85Afd8].Amount;
   }

   function b()public view  returns (uint){
       return Transactionss[0].Amount;
   }


}

執行函式 a 將給出 101。

執行函式 b 將給出 100。

為什麼?如何解決?

我正在查看其他回复,想知道​​我是否誤讀了這個問題。我的想法是,這是關於一種方法,而不是期望它是自動完成的。

它不會為您完成,但這是可行的,它是流行的儲存模式之一 - 帶有索引(和刪除可能性)的映射結構,又名 Solidity CRUD。

我對你的契約做了相當多的修改,以使其成為一種有效的東西。

你的問題實際上暗示了解決它的方法。實際上,結構本身需要“指向”索引中的行。就像是:

struct Transaction {
   address Creditor;
   uint Amount;
   uint arrayPointer; // <== row in array

組織事物的方法不止一種。一種流行的方法是保留一組主鍵:

address[] public transactionAddresses;  // <== array of primary keys

因此,不是對象本身。只是我們需要迭代列表的鍵,以便我們可以列舉鍵,因此我們可以從…中獲取感興趣的鍵

mapping(address => Transaction) public TransactionsMap; // map of objects for random access

偉大的。這是一個雙向綁定。如果您有一個數組行,則您有密鑰,因此您可以檢查該對象。如果您有該對象,您可以看到它在列表中的哪一行。我們只需要邊走邊維護它。

function addTransaction(address _address,uint _amount) public {
   Transaction memory newRequest = Transaction({
       Creditor: _address,
       Amount: _amount,
       arrayPointer: transactionAddresses.push(_address)-1});
   TransactionsMap[_address]=newRequest;
}

我最終得到了這個:

pragma solidity ^0.4.17;

contract Campaign {

   struct Transaction {
       address Creditor;
       uint Amount;
       uint arrayPointer; // <== row in array
   }
   address[] public transactionAddresses;  // <== array of primary keys
   mapping(address => Transaction) public TransactionsMap; // map of objects for random access

   function addTransaction(address _address,uint _amount) public {
       Transaction memory newRequest = Transaction({
          Creditor: _address,
          Amount: _amount,
          arrayPointer: transactionAddresses.push(_address)});
       TransactionsMap[_address]=newRequest;
   }
   function Testing()public {
       addTransaction(0xaef0B7Edd5D2E9315027ADFA4642E16a5c85Afd8,100);
       TransactionsMap[0xaef0B7Edd5D2E9315027ADFA4642E16a5c85Afd8].Amount++;
   }
   function a()public view  returns (uint){
       return TransactionsMap[0xaef0B7Edd5D2E9315027ADFA4642E16a5c85Afd8].Amount;
   }
   function b()public view  returns (address){
       return transactionAddresses[0];
   }
}

如果可以接受僅附加過程,則可以使用不帶指針的 Mapped Struct with Index。在這種情況下,不需要結構中的指針。指針的主要優點是,如果 Set 成員是瞬態的,它可能會在邏輯上從 Set 中刪除項目,這可能是必要的。

此處(2017 年)更詳細地解釋了該模式:https ://medium.com/robhitchens/solidity-crud-part-1-824ffa69509a

它的可重用程式碼庫(2019 年)在這裡:https ://github.com/rob-Hitchens/UnorderedKeySet和解釋器:https ://medium.com/robhitchens/solidity-crud-epilogue-e563e794fde

Solidity CRUD 與其他模式的比較:Solidity是否有很好解決且簡單的儲存模式?

希望能幫助到你。

我假設您的意思是您Testing首先呼叫該函式。或者合約名稱已更改,Testing函式實際上應該是建構子。無論如何,我假設它以某種方式被呼叫,否則兩者a都會b給你錯誤,因為沒有儲存任何東西。

因此,在執行完第一行之後,Testing數組Transactionss有一個具有 value的條目100TransactionsMap[0xaef0B7Edd5D2E9315027ADFA4642E16a5c85Afd8]也有一個具有 value 的條目100。第二行將Testingat 的值增加TransactionsMap[0xaef0B7Edd5D2E9315027ADFA4642E16a5c85Afd8]一 ( ++)。

也是如此TransactionsMap[0xaef0B7Edd5D2E9315027ADFA4642E16a5c85Afd8].Amount101並且Transactionss[0].Amount具有100您也可以從您的view功能中獲得的價值。

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