Solidity
如何正確初始化嵌套儲存數組/結構?
contract Contract { struct A { int a; } struct B { A[] as; } mapping(address => B[]) bs; function addB(B memory b) { bs[msg.sender].push(...???...); } }
我嵌套了一堆數組和結構,我不知道如何正確地將一個 B 添加到
bs
.
嵌套地獄
是的。
這是循環的:
struct B { B[] as; }
B 包含 B 的數組?
結構內部結構的動態數組推動了編譯器可以處理的限制。您必須構造該結構的記憶體實例並使用不存在的 push 方法,然後將作品複製到儲存中。
作為一般建議,不要與之抗爭,而是使用鍵數組並將結構放在可以在結構之外訪問的映射中。
大致:
struct Inner { members ... } struct Outer { address[] InnerKeys; more members ... } mapping(address => Inner) innerStructs; mapping(address => Outer) outerStructs;
酌情使用地址、bytes32 或 uint 作為鍵。
你會發現更容易應對。
你沒有說你需要用這個做什麼。它通常與臨時集有關,例如使用位置、成員資格等,這可能意味著需要在邏輯上刪除和迭代成員。您可能會發現這種方法很有用:https ://github.com/rob-Hitchens/UnorderedKeySet
這個小小的塗鴉在應用程序級別的問題上取得了不錯的進展,而不是陷入組織。
pragma solidity ^0.5.1; import "./HitchensUnorderedAddressSet.sol"; contract NestedStructs { using HitchensUnorderedAddressSetLib for HitchensUnorderedAddressSetLib.Set; struct UserStruct { uint balance; bool active; HitchensUnorderedAddressSetLib.Set followingSet; HitchensUnorderedAddressSetLib.Set followerSet; } mapping(address => UserStruct) userStructs; HitchensUnorderedAddressSetLib.Set userSet; function createUser(address user) public { // access control is set aside for brevity UserStruct storage u = userStructs[user]; userSet.insert(user); // revert on deuplicate keys u.active = true; } function join() public { createUser(msg.sender); } function followUser(address followed ) public { require(userSet.exists(msg.sender), "Join first please."); require(userSet.exists(followed), "Follow a joined user please."); UserStruct storage u = userStructs[msg.sender]; UserStruct storage f = userStructs[followed]; u.followingSet.insert(followed); f.followerSet.insert(msg.sender); // these revert on duplication } function unFollowUser(address unfollow) public { // You can add requires to create more app/human friendly error messages UserStruct storage u = userStructs[msg.sender]; UserStruct storage f = userStructs[unfollow]; u.followingSet.remove(unfollow); f.followerSet.remove(msg.sender); // these revert if there was no follower join to start with } function isUser(address user) public view returns(bool) { return userSet.exists(user); } function userCount() public view returns(uint) { return userSet.count(); } function userInfo(address user) public view returns(uint balance, bool active, uint followingCount, uint followerCount) { UserStruct storage u = userStructs[user]; balance = u.balance; active = u.active; followingCount = u.followingSet.count(); followerCount = u.followerSet.count(); } function userFollowerAtIndex(address user, uint index) public view returns(address) { return userStructs[user].followerSet.keyAtIndex(index); } function userFollowingAtIndex(address user, uint index) public view returns(address) { return userStructs[user].followingSet.keyAtIndex(index); } }
這裡還有另一個使用 Set 庫的範例:Efficient Solidity storage pattern for a directional weighted graph
希望能幫助到你。