將數組中每個結構的主鍵映射到他們自己
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的條目100
,TransactionsMap[0xaef0B7Edd5D2E9315027ADFA4642E16a5c85Afd8]
也有一個具有 value 的條目100
。第二行將Testing
at 的值增加TransactionsMap[0xaef0B7Edd5D2E9315027ADFA4642E16a5c85Afd8]
一 (++
)。也是如此
TransactionsMap[0xaef0B7Edd5D2E9315027ADFA4642E16a5c85Afd8].Amount
,101
並且Transactionss[0].Amount
具有100
您也可以從您的view
功能中獲得的價值。