1

I need to chunk an array of objects so i write:

function conditionalChunk(array, size, rules = {}) {
    let copy = [...array],
        output = [],
        i = 0;

    while (copy.length)
        output.push(copy.splice(0, rules[i++] ?? size))


    return output
}

and it works fine if I have rules like { 0: 2, 1: 2 }

 const input = [[1,2,3],[4,5,6,7]],
                output = conditionalChunk(input.flat(), 3, { 0: 2, 1: 2 });
          
    // OUTPUT: [[1,2],[3,4],[5,6,7]]

but when I have rules at the end like { 0: 2, 1: 2, 2:0, 5:0 } my function ignore to create empty arrays at the end.

the output I need is:

const input = [[1,2,3],[4,5,6,7]],
                    output = conditionalChunk(input.flat(), 3, { 0: 2, 1: 2, 2:0, 5:0 });
              
        // OUTPUT: [[1,2],[3,4],[],[5,6,7],[]]

so I just need to not ignore rules for empty arrays at the end of array. How I can do that?

8
  • what happens to the array at index 5 in the result set? Commented Jul 27, 2022 at 15:32
  • it should be add at the end of array as empty, not need to be at position 5 Commented Jul 27, 2022 at 15:33
  • in rule, it could be also 4 or any larger value to get an empty array at the end, right? Commented Jul 27, 2022 at 15:37
  • yes, it could be 10: 0 Commented Jul 27, 2022 at 15:44
  • Your code is actually working as intended. The problem with needing empty arrays after copy is empty is a function call like const input = [[1,2,3],[4,5,6,7]], output = conditionalChunk(input.flat(), 3, { 0: 2, 1: 2, 2:0, 7:0 }); would now be legitimate Commented Jul 27, 2022 at 15:44

4 Answers 4

1

Finally, you could check the keys of rules and if greater or equal to the next index of output push an empty array.

function conditionalChunk(array, size, rules = {}) {
    let output = [],
        i = 0;

    while (i < array.length)
        output.push(array.slice(i, i += rules[output.length] ?? size));
    
    let l = Object.keys(rules).reduce((l, v) => l + (v >= output.length), 0);

    while (l--) output.push([]);

    return output;
}

console.log(conditionalChunk([1, 2, 3, 4, 5, 6, 7], 3, { 0: 2, 1: 2 })); // [[1,2],[3,4],[5,6,7]]
console.log(conditionalChunk([1, 2, 3, 4, 5, 6, 7], 3, { 0: 2, 1: 2, 2: 0, 5: 0 })); // [[1,2],[3,4],[],[5,6,7],[]]
console.log(conditionalChunk([1, 2, 3, 4, 5, 6, 7], 3, { 0: 0, 1: 2, 8: 0, 7: 0, 9:0, 20:0 }));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

Comments

0

maybe you can try this, I prefer for...each loop in place of a while.

function conditionalChunk(array, size = 1, rules = {}) {
    let copy = [...array],
        output = [],
        i = 0;


        for (const rule of Object.keys(rules)) {
            let val = copy.splice(0, rules[rule] || size);
      if (typeof val === 'undefined') val = [];
      
      output.push(val);
    }

    return output;
}

var results = conditionalChunk([1, 2, 3, 4, 5], 2, { 0:2, 1: 2, 2:2, 3:0 });

console.log(results, '::results::');

https://jsfiddle.net/5ozbj7na/

2 Comments

Code dont work for rules like: var results = conditionalChunk([1, 2, 3, 4, 5], 2, { 0:0, 1: 2, 2:2, 11:0, 10:0 }); ... seems that do not create empty at the start ...
This wont work when rules is empty
0

A solution to your problem would be to add this bit of code after the while loop before the return statement

output.length = Math.max.apply(null, [output.length, ...Object.keys(rules)]) || output.length;
    
for (r in rules)
{
    output[r] = new Array(rules[r]);
}

It just extends the output array to the desired length then populates required spots with empty arrays (sorry for the complicated first line but JavaScript is complicated so :| ...)

3 Comments

I will test now
@AleksPer sure thing. I hope it works (at least on my end it does)
console.log(conditionalChunk([1, 2, 3, 4, 5, 6, 7], 3, { 0: 0, 1: 2, 8: 0, 7: 0, 9:0, 20:0 }));
0

Please try this one, this should work for you and is done based on your solution, so it should be easier to understand

  function conditionalChunk(array, size, rules = {}) {
  let copy = [...array],
    output = [],
    i = 0;

  while (copy.length) output.push(copy.splice(0, rules[i++] ?? size));

  const arr = Object.keys(rules).filter((key) => key > i);

  arr.forEach((key) => {
    if (rules[key] === 0) output.push([]);
  });

  return output;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.