返回反映結構關聯之間全域狀態的映射數組?
我正在尋找一種類似於“返回鍵值對列表”的構造,我認為它可以作為映射數組來實現。是對的嗎?
也就是說,我想要一個包含 (key,value) 列表的資料結構,我將使用它作為全域狀態,將一些結構連結到另一個結構。
我的意思是這樣的:
// so I have place structs struct Place { uint8 placeid; string nameOfPlace; ...etc } // and a place can contain no more than 1 banner. // banners have all been to a place, but they aren't necessarily // in a place right now. They may have been replaced with another // banner. struct Banner { uint8 bannerid; uint8 placeAt; // this must match a placeid string thingTheBannerSays; uint8 timestamp; } Place[] places; // list all places mapping(uint8 => Place) placesById // given an id, return the place Banner[] banners; mapping(uint8 => Banner) bannersById // given an id, return the place // what's missing for me is a data structure // with global state of [(place0,bannerN),(place1,bannerM)] // for all places. This is what I'm looking for. function listBannersAtPlacesRightNow() returns (???? arrayOfMappings) { ??? mappings[] = arrayOfMappings for(uint8 i =0; i < places.length; i++) { maxTime[i] = 0; // declare this correctly idWhereMaxTime[i] = 0; // gross, would rather be null for(uint8 j=0; j < banners.length; j++) { if(banners[j].timestamp > maxTime[i]) { maxTime[i] = banners[j].timestamp // high water ; idWhereMaxTime[i] = banners[j]; } } arrayOfMappings[i] = (places[i], idWheremaxTime[i]); } return arrayOfMappings; }
抱歉,我對此很陌生,但如果不清楚,換句話說,我想要一些變數來維持全域狀態,即“我是一個地方,我可以有 0 或 1 個橫幅。這是一個列表“
醜陋的準蟒蛇可能會澄清醜陋的準堅固性,這將是這樣的:
places = [{"placeid": 0, "nameofplace": "home"}, {"placeid":1, "nameofplace": "center"}] banners = [ {"bannerid": 0, "placeAt": 0, "thingthebannersays": "hello!"}, {"bannerid": 1, "placeAt": 0, "thingthebannersays": "hello again from home!"}, {"bannerid": 2, "placeAt": 0, "thingthebannersays": "this replaces 1!"}, {"bannerid": 3, "placeAt": 1, "thingthebannersays": "this is at center!"}] bannerAtPlaces = [(0,2), #place 0 has current banner 2 (1,3) #place 1 has banner 3 ] def setBannerAtPlaces(placeid, bannerid): # this updates bannerAtPlaces according to some rules # such as the most-recent timestamp given in the solidity # section # BUT If I wanted to see which places contained which banners, I'd just # print(bannerAtPlaces). This is the call I'm looking to repeat # in solidity.
這一切都出現了,因為我寧願讓 Place 的結構包含一個用於bannerid 的欄位,但不幸的是,我希望 Place 能夠擁有 0 個橫幅,而且看起來我無法為此初始化 null —我必須預設為
bannerid = 0
. 但是bannerid==0
是一個真正的bannerid。它不能同時出現在兩個地方,它已經在其他地方,並且不能成為所有新地方的橫幅的預設設置。指定全域狀態的列表的原因是為了在瀏覽器中輕鬆呈現它,作為顯示所有 (Place, Banner) 對的畫廊。
我現在在這裡看到一個類似的問題。
我不太確定你描述的基數。我選擇了“橫幅一次只能出現在一個地方,而一個地方要麼有或沒有正好有 1 個橫幅。”
for
循環是 Solidity 中的嚴重問題。我們需要組織資料結構,以便我們可以在任何規模上以一致的 gas 成本完成所有事情 - O(1)。看到這個:https ://blog.b9lab.com/getting-loopy-with-solidity-1d51794622ad我不認為你需要一對多的加入,但如果你確實看看這個想法:https ://medium.com/@robhitchens/enforcing-referential-integrity-in-ethereum-smart-契約-a9ab1427ff42
該連結有點讓您陷入困境。它連結到 CRUD 系列,該系列解釋了我用來繪製這個快速草圖的模式:
pragma solidity 0.4.25; contract Banners { struct BannerStruct { string marque; bytes32 placeId; // 0 or 1 placeId uint idPointer; } struct PlaceStruct { string name; bytes32 bannerId; // 0 or 1 bannerId uint idPointer; } mapping(bytes32 => BannerStruct) public bannerStructs; mapping(bytes32 => PlaceStruct) public placeStructs; bytes32[] public bannerIdList; bytes32[] public placeIdList; function getBannerCount() public view returns(uint) { return bannerIdList.length; } function getPlaceCount() public view returns(uint) { return placeIdList.length; } function isBanner(bytes32 bannerId) public view returns(bool) { if(bannerIdList.length==0) return false; // there aren't any, so false return bannerIdList[bannerStructs[bannerId].idPointer] == bannerId; } function isPlace(bytes32 placeId) public view returns(bool) { if(placeIdList.length==0) return false; return placeIdList[placeStructs[placeId].idPointer] == placeId; } function placeHasBanner(bytes32 placeId) public view returns(bool) { return isBanner(placeStructs[placeId].bannerId); } function newBanner(bytes32 bannerId, string marque) public returns(bool) { require(!isBanner(bannerId)); // no dups bannerStructs[bannerId].marque = marque; bannerStructs[bannerId].idPointer = bannerIdList.push(bannerId) - 1; return true; } function newPlace(bytes32 placeId, string name) public returns(bool) { require(!isPlace(placeId)); placeStructs[placeId].name = name; placeStructs[placeId].idPointer = placeIdList.push(placeId) - 1; return true; } function setPlaceBanner(bytes32 placeId, bytes32 bannerId) public returns(bool) { require(isPlace(placeId)); require(isBanner(bannerId)); if(bannerStructs[bannerId].placeId != 0) { // moving it. A banner can only be in one place??? bytes32 oldPlace = bannerStructs[bannerId].placeId; placeStructs[oldPlace].bannerId = bytes32(0); } bannerStructs[bannerId].placeId = placeId; placeStructs[placeId].bannerId = bannerId; } }
當您繼續往下看時,您還會發現您可能希望減少儲存在鏈上的元數據量。出於這個原因,我的結構很稀疏。https://blog.b9lab.com/the-joy-of-minimalism-in-smart-contract-design-2303010c8b09
希望能幫助到你。