3

I have a mapping and an array that contains a list of addresses of students. When I loop over that array, the method .length is not working.

How can I loop through the array Student_list shown below?

 mapping(address => Student) Students;
 address [] public Student_list;

  function Studentgrade() public{

for (uint i=0; i<Student_list.length; i++) {
if (Students[Student_list[uint(i)]].grade <= Maxvalue) {
     Students[Student_list[uint(i)]].grade=  90;

}
}
}
5

You haven't described enough about your testing methodology for me to know why it appears that the .length method isn't working. It does.

One possibility is you are expecting a response but the function is state-changing so you will only get a transaction hash. Another possibility is the array isn't populated the way you expect or your inspection functions (not shown) don't work as expected.

The example below has a simple function to populate the student data. It doesn't check for duplicates to keep the example on point. I added an event emitter to make it easier to inspect the iterations, and a getter function so you can inspect the array length directly. Some names have been changed to bring things into alignment with the style guide.

pragma solidity 0.4.25;

contract Loop {

    struct StudentStruct {
        uint grade;
    }

    mapping(address => StudentStruct) public studentStructs;
    address [] public studentList;

    event LogStudentGrade(address student, uint studentGrade);

    function appendStudentGrade(address student, uint studentGrade) public {
        studentList.push(student);
        studentStructs[student].grade = studentGrade;
    }

    function getStudentCount() public view returns(uint count) {
        return studentList.length;
    }

    function studentLoop() public {

        // WARN: This unbounded for loop is an anti-pattern

        for (uint i=0; i<studentList.length; i++) {
            emit LogStudentGrade(studentList[i], studentStructs[studentList[i]].grade);
        }
    }
}

The WARN is about caution with for loops in Solidity. I assume you're just starting out and only wish to see this work as expected. This is a warning for others.

In Remix:

  1. Deploy the contract
  2. Add students, score. Repeat multiple times if you want.
  3. Inspect the count function.
  4. Sent a transaction to the studentLoop
  5. Inspect the transaction Log.

Here it is in Remix to show it working.

enter image description here

Hope it helps.

  • Thanks. I can loop now. But I should first call a function to get the number of elements in the array first as following: uint x=getStudentCount() then I can use x inside the loop as for (uint i=0; i<=x; i++). I tried to put studentList.length inside the loop directly but it does not work with me and the remix gives me invalid opcode error – Mohamed Oct 9 '18 at 22:30
  • 1
    I'd have to see the actual code to know what went wrong. As you can see, my code uses for(i=0, i<studentList.length; i++) {} and it works. Just to say what you want isn't unreasonable. Unfortunately, the invalid OPCODE could arise from anywhere. The debugger can help identify the step it was on when things went sideways. – Rob Hitchens - B9lab Oct 10 '18 at 1:09

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.