【问题标题】:How to return mapping list in Solidity? (Ethereum contract)如何在 Solidity 中返回映射列表? (以太坊合约)
【发布时间】:2016-10-03 01:48:07
【问题描述】:

我想做一个简单的智能合约,它有一个列表,可以设置项目,并且可以获取列表。

可靠的代码:

contract lister {
    mapping(int => string) list;
    int id = 0;

    function getList() returns ( /*HERE*/ ) {
        return list;
    }

    function setItemToList(string str) {
        list[id] = str;
        id++;
    }
}

我想让 getList() 返回列表,但返回类型不兼容。 我该怎么做?

【问题讨论】:

    标签: ethereum solidity


    【解决方案1】:

    在 Solidity 中批量访问列表/数组/等是很痛苦的。你很少在合同中看到它。在您的情况下,一种可能的解决方案是提供一个函数来访问 one 项,使用它的索引,并让调用者从 0 循环到 id。

    【讨论】:

    • 我只是在熟悉 Solidity,但这让我感到惊讶。如何构建任何有用的应用程序?我们是否应该实际上将数据保存在其他地方(在非以太坊应用程序中)并使用 dapp 与之交互并验证数据完整性?
    • 我相信这个问题的答案是肯定的。事实上,您可以看到哪些网站可以这样做,因为无需安装元掩码即可访问它们。
    • 我仍在寻找这个问题的答案,到目前为止,似乎在不执行 for 循环/速率限制的情况下访问整个列表的唯一方法是处理事务/事件历史记录并自己存储数据……这意味着我需要在我自己的存储和区块链之间始终保持数据同步……
    【解决方案2】:

    使用映射,不存储键并且不能迭代值,因此它们实际上只适用于单值查找。在您提供的示例中,使用数组可能是更好的选择。

    另一方面,如果您使用数组并需要对其进行搜索(循环遍历所有项目),则需要小心,因为如果数组中的项目太多,最终可能会花费调用该函数需要大量的气体。

    【讨论】:

      【解决方案3】:

      您可以更改变量 list 的可见性,插入 public 并且可以通过 getList 访问它。

      mapping(int => string) public list;

      【讨论】:

      • 你不应该这样做。这使得任何人都可以使用地图。所以他们可以在不知道键值的情况下访问地图。
      • @e.k 看起来 OP 想让任何人都可以使用该地图。是否有任何其他原因这是不好的做法,或者如果你想保持私密性就不好?
      • 这是否让任何人都可以编辑它?
      【解决方案4】:

      映射不存储它们的键,只存储存储在状态内存地址的值。要获取数据列表,请使用数组。

      address[] public addresses;
      

      现在定义一个函数来获取这个数组的长度:

         function getAddressCount() public view returns(uint){
              return addresses.length;
          }
      

      另外定义一个函数来通过索引获取元素:

      function getAddressByIndex(uint index) public view returns(address){
      
         return addresses[index]
      }
      

      现在您需要编写代码来逐个获取数组。这是使用 web3 库在 javascript 中完成的方式:

      let addresses,addressCount;
      try {
           addressesCount = await ContractName.methods.getCampaignCounts().call();
             
          addresses = await Promise.all(
            Array(parseInt(addressesCount))
              .fill()
              .map((element, index) => {
                return ContractName.methods.getAddressByIndex(index).call();
              })
          );
          
        } catch (e) {
          console.log("error in pulling array list", e);
        }
      

      【讨论】:

        猜你喜欢
        • 2018-10-16
        • 2021-12-26
        • 2019-05-09
        • 2016-02-28
        • 2020-03-14
        • 2018-08-09
        • 1970-01-01
        • 1970-01-01
        • 2018-03-15
        相关资源
        最近更新 更多