0

Following up on the question of 2d array of different types: 2d array of different types?

How would one go about initializing a new array of structs (Vote) when creating a new struct (Project)

pragma solidity ^0.4.25;

contract Votinggame{

       struct Vote {
          address voter;
          string comment;
      }

        struct Project{
            int id;
            string name;
             int votes;
            Vote[] vote;
        }

        Project[] public projects;
        int idcounter=-1;

     function addNewProject(string name) public {

             Project memory newProject = Project({
                 id:idcounter+1,
                 name:name,
                 votes:0

                 // How to initialise new vote array of struct Vote inside Project struct ??
                 // vote: new Vote[](0) -> this is not working "UnimplementedFeatureError: Copying of type struct HotOrNotCrypto.Vote memory[] memory to storage not yet supported."

             });
           idcounter=newProject.id;
           projects.push(newProject); 
        }

      function vote(uint index , string comment) public {
        Project storage project = projects[index];
        project.votes++;     
        Vote memory v;
        v.voter = msg.sender;
        v.comment = comment;
        project.voters.push(v);
      }
    }
 function getProjects() public view returns (uint){
         return (projects.length);
       }
}

Also to extend on this how would one go about displaying vote Array of Vote struct in React. At the moment I'm displaying projects Array of a projects struct using .fill().map()

  static async getInitialProps(){

    const getProjects = await Contract.methods.getProjects().call();
    const projectsList = await Promise.all(
    Array(parseInt(getProjects))
    .fill()
    .map((element, index)=> {
      return Contract.methods.projects(index).call()
    }));
  const sorted_projects = _.orderBy(projectsList, ['votes'], ['desc']);


   return { sorted_projects};

  }

and then render new table row for each struct element like so:

  renderRow(){
    return (

      this.props.sorted_projects.map((sorted_projects,key)=>{
      return <RequestRow
        id= {key+1}
        key ={key}
        sorted_projects ={sorted_projects}
      />;

  }));

I guess this will be sort of similar with the difference that I would have to provide which project index I want votes array to display

1

Your best bet is to use the following way:


    function addNewProject(string name) public {
        uint lastIndex = projects.length++;
        Project storage project = projects[lastIndex];
        project.id = ++idcounter;
        project.name = name;
    }

All undefined storage is already defined as zero-ish. A zero-ish array is an empty array. So:

  • project.votes is already 0, no need to set it.
  • project.vote is already initialised to an empty array.

Plus, you need not do project.votes++; because that is the same information as project.voters.length, so save yourself some gas.

You may want to make Project[] private projects; and write the getter yourself, so that you can return project.voters.length among others.

Oh, and better naming: function getProjectCount()

  • I do need to give value to all the fields in the struct when declaring a new one, otherwise, the compiler will complain. – Damian Klepacki Oct 17 '18 at 17:18
  • That's news to me. AFAIK it does not complain if you omit variable length elements like a Vote[] vote;... – Xavier Leprêtre B9lab Oct 17 '18 at 21:21
  • Ooh I updated my answer as I could reproduce your issue. – Xavier Leprêtre B9lab Oct 17 '18 at 21:41
0

As the error message asserts, this isn't something Solidity supports yet. One of the common patterns instead is to store a separate array of Votes, and maintain an index into those (using uint256[]) in the Project struct:

pragma solidity ^0.4.24;

contract Votinggame{
  struct Vote {
    address voter;
    string comment;
  }

  struct Project{
    uint256 id;
    string name;
    uint256 votes;
    uint256[] voteArr;
  }

  Project[] public projects;
  Vote[] public votes;

  uint256 projectCounter = 0;
  uint256 voteCounter = 0;

  function addNewProject(string name) public {
    projects.push(Project({
      id: projectCounter,
      name: name,
      votes: 0,
      voteArr: new uint256[] (0)
    }));

    projectCounter += 1;
  }

  function vote(uint index , string comment) public {
    Vote memory v;
    v.voter = msg.sender;
    v.comment = comment;
    votes.push(v);

    projects[index].votes += 1;
    projects[index].voteArr.push(voteCounter);

    voteCounter += 1;
  }
}

To access this, then, you:

  1. Pull the Project from projects using the project index
  2. Inspect the project.votes value
  3. Iterate from 0 to votes - 1 getting the vote's index
  4. Pull the Vote from votes using the vote index
  • This make sense, I will try implementing this and let you know if it works for what I want it to work – Damian Klepacki Oct 17 '18 at 17:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.