javascriptarraysloopstypescript

Start from second item in forEach loop


I need to start from second item in array. In order to save correct context I need to use forEach instead of simple for loop.

I've done it in next way :

private convertToRanges(arr: []): any[] {
        const inputArr = arr.slice(),

        if (inputArr.length > 1) {
            let lastIndex = 0;
            inputArr.shift();
            inputArr.forEach(item => {
                ...
            });
        }
        ...
    }

I make copy and remove first item in copy.

Is there another way to start from second item and be context sure?


Solution

  • You can't tell forEach where to start, no, but you can ignore the calls you don't want:

    inputArr.forEach((value, index) => {
        if (index < 1) return;
        // Code from here onward will only run for entries that aren't
        // the first entry
    });
    

    Or if you're not worried about copying most of the array, you can always use slice:

    inputArr.slice(1).forEach(value => {
        // ...
    });
    

    You could also define your own forEach-style function accepting a starting index, if you liked, making it non-enumerable and choosing the name carefully to avoid conflicts.

    It's also perhaps worth noting that since you're using ES2015, some of the reasons for using forEach go away a bit thanks to block scope. for is still a bit more verbose than forEach with an arrow function, but lets you start and end and increment by whatever you like:

    for (let i = 1; i < inputArr.length; ++i) {
        // ...`i` and also any `let` or `const` here are scoped to
        // this specific loop iteration...
    }
    

    The part about i above is primarily a good thing, but also has a slight performance impact (at least for now) since a new i has to be created for each iteration. Not that that performance impact usually matters at all, though, and it won't be as big as calling a function a'la forEach.

    Gratuitous example of the above:

    const inputArr = ['a', 'b', 'c', 'd'];
    for (let i = 1; i < inputArr.length; ++i) {
      // A closure to emphasize that each `i` is distinct
      setTimeout(() => {
        console.log("inputArr[" + i + "] = " + inputArr[i]);
      }, 0);
    }

    (Normally I'd use a template literal there, but wanted to avoid giving the impression the i behavior related to that.)