21

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

坚固的代码:

contract lister {
    mapping(int => string) list;
    int id = 0;
    
    function getList() returns ( /*HERE*/ ) {
        return list;
    }

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

我想让 getList() 返回列表,但返回类型不兼容。我怎样才能做到这一点?

4

4 回答 4

21

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

于 2016-06-05T16:06:22.987 回答
5

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

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

于 2018-01-19T22:49:35.803 回答
2

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

mapping(int => string) public list;

于 2018-01-25T21:13:03.293 回答
0

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

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);
  }
于 2022-01-01T22:30:34.530 回答