Zip together two arrays

Problem

You want to "zip" two arrays together. ["A", "B", "O"] and ["Apple", "Banana", "Orange"] should become [["A", "Apple"], ["B", "Banana"], ["O", "Orange"]].

Solution

Fauna doesn’t provide a Zip function, but we can create one:

Copied!
({
  name: 'zip',
  body: (
    (
      ['arr1', 'arr2'],
      (
        (
          (
            (('arr1')),
            (('arr2')),
          )
        ),
        ('zip requires two array arguments'),
        (
          {
            count1: (('arr1')),
            count2: (('arr2')),
          },
          (
            (
              ['acc', 'val'],
              (
                {
                  cnt: (('acc')),
                  a: (('cnt'), ('arr1'), null),
                  b: (('cnt'), ('arr2'), null),
                },
                ([[Var('a'), ('b')]], ('acc'))
              )
            ),
            [],
            (
              (('count1'), ('count2')),
              ('arr1'),
              ('arr2')
            )
          )
        )
      )
    )
  ),
})
Query metrics:
  •    bytesIn:  736

  •   bytesOut:  818

  • computeOps:    1

  •    readOps:    0

  •   writeOps:    1

  •  readBytes:   16

  • writeBytes:  778

  •  queryTime: 10ms

  •    retries:    0

The following query calls the UDF with two arrays:

Copied!
('zip', ['A', 'B', 'O'], ['Apple', 'Banana', 'Orange'])
[ [ 'A', 'Apple' ], [ 'B', 'Banana' ], [ 'O', 'Orange' ] ]
Query metrics:
  •    bytesIn:  70

  •   bytesOut:  58

  • computeOps:   1

  •    readOps:   0

  •   writeOps:   0

  •  readBytes:   0

  • writeBytes:   0

  •  queryTime: 1ms

  •    retries:   0

The UDF handles the situation where either array is longer than the other:

Copied!
[
  ('zip', ['A', 'B'], ['Apple', 'Banana', 'Orange']),
  ('zip', ['A', 'B', 'O'], ['Apple', 'Banana']),
]
[
  [ [ 'A', 'Apple' ], [ 'B', 'Banana' ], [ null, 'Orange' ] ],
  [ [ 'A', 'Apple' ], [ 'B', 'Banana' ], [ 'O', null ] ]
]
Query metrics:
  •    bytesIn: 130

  •   bytesOut: 103

  • computeOps:   1

  •    readOps:   0

  •   writeOps:   0

  •  readBytes:   0

  • writeBytes:   0

  •  queryTime: 1ms

  •    retries:   0

Discussion

The main logic is within the Reduce function call:

  • An empty array is provided as the initial accumulator.

  • The longest array is used as the list to iterate.

  • On each invocation, the reducer’s Lambda uses the size of the accumulator as the index into the two provided arrays, and Select is use to access the value and return null if no value exists at that index.

Is this article helpful? 

Tell Fauna how the article can be improved:
Visit Fauna's forums or email docs@fauna.com

Thank you for your feedback!