Yevhen Klymentiev
dark
light
console
darkness
y.klymentiev@gmail.com
Reusable Snippets|Practical utility code for everyday use — custom-built and ready to share

zipWithPadding

Zips two arrays into an array of pairs (tuples). Pads shorter array with 'undefined' or provided default values.

TypeScript
Copied!
1/**
2 * Zips two arrays into an array of pairs (tuples).
3 * Pads shorter array with 'undefined' or provided default values.
4 *
5 * @param a - First array.
6 * @param b - Second array.
7 * @param padA - Optional value to use if 'a' is shorter.
8 * @param padB - Optional value to use if 'b' is shorter.
9 * @returns Array of [a[i] || padA, b[i] || padB] pairs.
10 */
11export function zipWithPadding<T, U>(
12  a: T[],
13  b: U[],
14  padA?: T,
15  padB?: U
16): [T | undefined, U | undefined][] {
17  const length = Math.max(a.length, b.length);
18  return Array.from({ length }, (_, i) => [
19    i < a.length ? a[i] : padA,
20    i < b.length ? b[i] : padB,
21  ]);
22}
  • Handles arrays of unequal length

    Ensures that both arrays are zipped to the longest length, preventing loss of data from the longer array.

  • Customizable padding

    Accepts optional padding values (padA, padB) to fill missing entries, offering greater flexibility than undefined-only behavior.

  • Maintains tuple structure

    Returns consistent [T | undefined, U | undefined] tuple pairs, ensuring predictable access to elements even when one array is shorter.

  • Useful for non-destructive data merging

    Instead of truncating data to match lengths, this method preserves the full range of both inputs, which is critical in some merging scenarios.

  • Immutability and clarity

    Returns a new array without modifying the input arrays — useful in functional programming and predictable state management.

Tests | Examples

TypeScript
Copied!
1test('zipWithPadding - same length', () => {
2  expect(zipWithPadding([1, 2], ['a', 'b'])).toEqual([
3    [1, 'a'],
4    [2, 'b'],
5  ]);
6});
7
8test('zipWithPadding - second array longer', () => {
9  expect(zipWithPadding([1], ['a', 'b'])).toEqual([
10    [1, 'a'],
11    [undefined, 'b'],
12  ]);
13});
14
15test('zipWithPadding - first array longer', () => {
16  expect(zipWithPadding([1, 2], ['a'])).toEqual([
17    [1, 'a'],
18    [2, undefined],
19  ]);
20});
21
22test('zipWithPadding - both arrays empty', () => {
23  expect(zipWithPadding([], [])).toEqual([]);
24});
25
26test('zipWithPadding - with custom padding values', () => {
27  expect(zipWithPadding([1], ['a', 'b'], 0, 'x')).toEqual([
28    [1, 'a'],
29    [0, 'b'],
30  ]);
31});

Common Use Cases

  • Aligning datasets of different lengths

    Useful when combining user input with defaults, logs with timestamps, or form labels with field values where one list may be shorter.

  • Creating padded tabular structures

    Can be used in rendering UIs or CSVs where missing values should appear as empty cells or defaults.

  • Graceful degradation in merging

    Prevents runtime errors by ensuring there's always a value (or fallback) in each tuple, even if only from one side.

  • Data normalization

    In ETL pipelines or spreadsheets, this is helpful when aligning rows or columns that came from inconsistent data sources.

  • Safe pairing in mapping transformations

    Allows developers to map over a combined dataset even when inputs aren’t symmetric in length, without introducing index errors.

Codebase: Utilities -> Arrays -> zipWithPadding | Yevhen Klymentiev