Search code examples
phploopsforeachlogic

simple loop that wraps around string not working?


Basically, I am wanting to generate arbitrary length string of musical notes, for example from A to G where after G it naturally wraps around to A in another octave. So far, I have this:

function generateNotes($start, $numbers) {
    $notes = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];

    $indice = array_search($start, $notes);

    foreach (range(0, $numbers-1) as $number) {
    
        
        if(($number + $indice) >= count($notes)) {
                $number -= count($notes);
        } 
        
        echo ($number + $indice) . " ";
        
    }

}

echo generateNotes('E', 24);

What I get is the following, which confuses me:

4 5 6 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 

It works the first time, 6 (being G) wrapping around to 0 (A), however the next time (number+indice) > 6 it never works again. Why does it only work the first time within the loop?


Solution

  • Your problem is that you are attempting to assign $number in the if block inside the foreach, but at the end of each loop, the value of $number is overwritten again by the foreach, so what you do has no effect. It's easier to just use modulo arithmetic instead:

    function generateNotes($start, $numbers) {
        $notes = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
        $num_notes = count($notes);
        $indice = array_search($start, $notes);
    
        foreach (range(0, $numbers-1) as $number) {
            echo (($number + $indice) % $num_notes) . " ";
        }
    }
    
    echo generateNotes('E', 24);
    

    Output:

    4 5 6 0 1 2 3 4 5 6 0 1 2 3 4 5 6 0 1 2 3 4 5 6 
    

    Demo on 3v4l.org