Skip to main content

forEachDual

Iterates over two arrays simultaneously, executing a callback function for each element pair. When arrays have different lengths, iterates based on the longer array's length, passing undefined for indices that exceed the shorter array's range. Supports early termination when the callback returns false.

Signature​

const forEachDual: <Type1, Type2>(array1: Type1[], array2: Type2[], callback: (item1: Type1 | undefined, item2: Type2 | undefined, index: number, array1: Type1[], array2: Type2[]) => boolean | void) => void

Parameters​

NameTypeDescription
array1-First array to iterate over
array2-Second array to iterate over
callback-Callback function to execute for each element pair

Examples​

Iterate arrays of same length​

import { forEachDual } from '@winglet/common-utils';

const names = ['Alice', 'Bob', 'Charlie'];
const ages = [30, 25, 35];

forEachDual(names, ages, (name, age, index) => {
console.log(`${index}: ${name} is ${age} years old`);
});
// Output: 0: Alice is 30 years old
// 1: Bob is 25 years old
// 2: Charlie is 35 years old

Handle arrays of different lengths​

const products = ['Laptop', 'Phone', 'Tablet', 'Watch'];
const prices = [999, 699, 399]; // Shorter array

forEachDual(products, prices, (product, price, index) => {
if (product === undefined) {
console.log(`${index}: No product, price: ${price}`);
} else if (price === undefined) {
console.log(`${index}: ${product} - No price available`);
} else {
console.log(`${index}: ${product} costs $${price}`);
}
});
// Output: 0: Laptop costs $999
// 1: Phone costs $699
// 2: Tablet costs $399
// 3: Watch - No price available

Early termination​

const numbers1 = [1, 2, 3, 4, 5];
const numbers2 = [10, 20, 30, 40, 50];

forEachDual(numbers1, numbers2, (a, b, index) => {
const sum = (a || 0) + (b || 0);
console.log(`${index}: ${a} + ${b} = ${sum}`);

if (sum > 50) {
console.log('Sum exceeded 50, stopping');
return false; // Stop iteration
}
});
// Output: 0: 1 + 10 = 11
// 1: 2 + 20 = 22
// 2: 3 + 30 = 33
// 3: 4 + 40 = 44
// 4: 5 + 50 = 55
// Sum exceeded 50, stopping

Compare and merge data​

interface OldUser { id: number; name: string; }
interface NewUser { id: number; email: string; }

const oldUsers: OldUser[] = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];

const newUsers: NewUser[] = [
{ id: 1, email: 'alice@example.com' },
{ id: 2, email: 'bob@example.com' },
{ id: 3, email: 'charlie@example.com' }
];

const mergedUsers: Array<{id: number; name?: string; email?: string}> = [];

forEachDual(oldUsers, newUsers, (oldUser, newUser, index) => {
const merged = {
id: oldUser?.id || newUser?.id || index,
name: oldUser?.name,
email: newUser?.email
};
mergedUsers.push(merged);
});

console.log(mergedUsers);
// [
// { id: 1, name: 'Alice', email: 'alice@example.com' },
// { id: 2, name: 'Bob', email: 'bob@example.com' },
// { id: 3, name: undefined, email: 'charlie@example.com' }
// ]

Parallel processing with validation​

const inputs = ['10', '20', 'invalid', '40'];
const expected = [10, 20, 30, 40];

forEachDual(inputs, expected, (input, expectedValue, index, arr1, arr2) => {
if (input === undefined || expectedValue === undefined) {
console.log(`${index}: Missing data`);
return;
}

const parsed = parseInt(input);
if (isNaN(parsed)) {
console.log(`${index}: Invalid input "${input}"`);
return false; // Stop on invalid data
}

const isMatch = parsed === expectedValue;
console.log(`${index}: ${input} -> ${parsed}, expected ${expectedValue}, match: ${isMatch}`);
});

Working with coordinates​

const xCoords = [1, 3, 5, 7];
const yCoords = [2, 4, 6]; // One less element

const points: Array<{x: number; y: number}> = [];

forEachDual(xCoords, yCoords, (x, y, index) => {
if (x !== undefined && y !== undefined) {
points.push({ x, y });
console.log(`Point ${index}: (${x}, ${y})`);
} else {
console.log(`Point ${index}: Incomplete coordinates (${x}, ${y})`);
}
});
// Output: Point 0: (1, 2)
// Point 1: (3, 4)
// Point 2: (5, 6)
// Point 3: Incomplete coordinates (7, undefined)

Playground​

import { forEachDual } from '@winglet/common-utils';

const names = ['Alice', 'Bob', 'Charlie'];
const ages = [30, 25, 35];

forEachDual(names, ages, (name, age, index) => {
console.log(`${index}: ${name} is ${age} years old`);
});
// Output: 0: Alice is 30 years old
//         1: Bob is 25 years old
//         2: Charlie is 35 years old

Notes​

Length Handling: Iterates based on the longer array's length. Elements from the shorter array are undefined when their indices are out of bounds.

Early Termination: Iteration stops immediately when the callback returns false. Any other return value (including undefined) continues the iteration.

Callback Parameters: The callback function receives five parameters:

  • item1: Current element from first array (or undefined)
  • item2: Current element from second array (or undefined)
  • index: Current index in the iteration
  • array1: The entire first array
  • array2: The entire second array

Performance: Uses Math.max to determine iteration length and direct array access for optimal performance with minimal overhead.