RobertK
RobertK

Reputation: 27

Nested loop with validation on whether to continue the loop or begin the next iteration

I have a object like so (replaced with dummy data for simplicity, in the real case each of the integer elements is an object):

const dummyObject = {
    A: [
        [ 1, 2 ],
        [ 3, 4 ],
        [ 5, 6 ]
    ],
    B: [
        [ 7 ],
        [ 8 ]
    ],
    C: [
        [ 9, 10, 11 ],
        [ 12, 13, 14 ],
        [ 15, 16, 17 ]
    ]
}

Note that all integer arrays (inner arrays) in each property A, B or C are of equal length, and the length of outer arrays (containing integer arrays) can vary. There can also be varying amount of properties (D, E, ...)

Now I want to loop over the arrays in a specific fashion, where each iteration forms a result array:

//
// Result arrays (18 total):
//

// 1st iteration
[ 1, 2, 7, 9, 10, 11 ]
// 2nd iteration
[ 1, 2, 7, 12, 13, 14 ]
// 3rd
[ 1, 2, 7, 15, 16, 17 ]
// 4th
[ 1, 2, 8, 9, 10, 11 ]
// 5th
[ 1, 2, 8, 12, 13, 14 ]
// ...
// 18th and final iteration
[ 5, 6, 8, 15, 16, 17 ]

I could manage to do this loop, but each time I append a integer array to a result array, I want to validate the result array. If the validation fails I want to discard the result array and start the next iteration. Example:

//
// Same loop, but validate result array after every update.
//

// 1st iteration: Result array fails validation after the "[ 7 ]" array is added to it,
// discard this result array and start the 2nd iteration immediately.
[ 1, 2, 7 ]
// 2nd iteration
// ...

Upvotes: 0

Views: 212

Answers (1)

Nenad Vracar
Nenad Vracar

Reputation: 122087

You could use cartesian product and also pass custom function to validate each row before adding it to a result.

const data = {
  A: [
    [1, 2],
    [3, 4],
    [5, 6]
  ],
  B: [
    [7],
    [8]
  ],
  C: [
    [9, 10, 11],
    [12, 13, 14],
    [15, 16, 17]
  ]
}

function iterate(data, validate = () => {}) {
  const result = [];

  function f(values, n = 0, c = []) {
    if (n === values.length) {
      const row = c.flat();
      const isValid = validate(row)
      if (isValid) result.push(row);
      else console.log('not valid', row)
      return;
    }

    for (let i = 0; i < values[n].length; i++) {
      c[n] = values[n][i]
      f(values, n + 1, c)
    }
  }

  f(Object.values(data))
  return result;
}

const validator = data => data.every(e => e !== 7)
const result = iterate(data, validator);
console.log(result)

Upvotes: 1

Related Questions