2016-06-07 16 views
1

매핑에서 동일한 키 아래에 여러 값을 가질 수 있어야합니다. 오늘날 Solidity의 매핑은 단일 값입니다. 값을 쓰는 것은 이전 값을 덮어 씁니다 (여전히 블록 체인에 있지만 계약으로 검색 할 수는 없습니다).솔리 션의 다중 값 매핑

contract MVM { 

    struct Bucket { 
    bool exists; 
    uint num; // Never decreases: we can only add records, not remove them. 
    mapping(uint => Record) records; 
    } 

    struct Record { 
    bool exists; 
    string info; 
    } 

    // Do not make it public: the compiler crashes when generating 
    // accessors https://github.com/ethereum/solidity/issues/633 
    mapping(string => Bucket) data; 

    function set(string key, string value) { 
    if (data[key].exists) { 
     data[key].records[data[key].num] = Record(true, value); 
    } 
    else { 
     data[key].exists = true; 
     data[key].records[0] = Record(true, value); 
    } 
    data[key].num++; 
    } 

    function num_of(string key) returns (uint) { 
    return data[key].num; // Guaranteed to be initialized as zero? 
    } 

    function get(string key, uint index) returns (string) { 
    if (!data[key].exists || !data[key].records[index].exists) { 
     throw; 
    } 
    return data[key].records[index].info; 
    } 

} 

geth 콘솔에서의 사용의 예 :

> mvs.set.sendTransaction("foo", "bar", {from:eth.accounts[0], gas: 1000000}) 
"0x79c52c437a94f3301775acec5639404eff563fce1a99ad097f5db28f109d7ab5" 

> mvm.set.sendTransaction("foo", "thing", {from:eth.accounts[0], gas: 1000000}) 
"0xb26b8d34691b0da5cb48af68933e81b514199f4ed8bd2b557767c8b55da85f50" 
> mvm.get.call("foo") 
"bar" 
> mvm.get.call("foo", 1) 
"thing" 
> mvm.num_of.call("foo") 
2 

내 접근 방식에 결함이 있는가 나는 멀티 가치 매핑을하려면이 코드를 작성? 또는 더 나은 해결책?

답변

1
contract MVM { 

    struct Record { 
    bool exists; 
    string info; 
    } 

    mapping(string => Record[]) data; 

    // If you want to iterate the whole thing, you can use this: 
    string[] keysNames; 

    function set(string key, string value) { 
     // Remove this if, if you don't need iteration 
     if (data[key].length == 0) { 
      keysNames.push(key); 
     } 

     data[key].push(Record(true, value)); 
    } 

    function num_of(string key) constant returns (uint) { 
    return data[key].length; 
    } 

    function get(string key, uint index) constant returns (string) { 
    if (data[key][index].exists == false) { 
     throw; 
    } 
    return data[key][index].info; 
    } 

    function exampleIterate() constant returns (string last) { 
     uint keysLen = keysNames.length; 

     for(uint i = 0; i < keysLen; i++) { 
     uint recordsLen = data[keysNames[i]].length; 

     for(uint j = 0; j < recordsLen; j++) {   
      last = data[keysNames[i]][j].info; 
     } 
     } 
    } 

}