DEV Community

Jarett Lee
Jarett Lee

Posted on

Which would you use? Regarding _.chunk

I was looking through the You Don't Need Lodash repo and I decided to take a crack at making my own _.chunk function.

// === sample 1 ===
// I think this is clear and avoids mutable data. The basic idea is:
//   1. make a new sub array when you need a new sub array
//   2. keep the old stuff and add the new thing to the end
const chunk = (input, size) => {
  return input.reduce((arr, item, idx) => {
    return idx % size === 0
      ? [...arr, [item]]
      : [...arr.slice(0, -1), [...arr.slice(-1)[0], item]];
  }, []);
};

// === sample 1.2 ===
// I think this is a slightly clearer way to state that you need a new sub array
const chunk = (input, size) => {
  return input.reduce((arr, item, idx) => {
    return arr.length === 0 || arr.slice(-1)[0].length === size
      ? [...arr, [item]]
      : [...arr.slice(0, -1), [...arr.slice(-1)[0], item]];
  }, []);
};

// === sample 1.3 ===
// Naming the sub array might be most clear.
const chunk = (input, size) => {
  return input.reduce((arr, item) => {
    const subArr = arr.slice(-1)[0];
    return arr.length === 0 || subArr.length === size
      ? [...arr, [item]]
      : [...arr.slice(0, -1), [...subArr, item]];
  }, []);
};


// === sample 2 ===
// I think this is also clear, but uses mutable data. The basic idea is:
//   1. fill a sub array
//   2. when a sub array is full, create a new sub array and append it to the
//      main array
const chunk = (input, size) => {
  return input.reduce(({arr, subArr}, item) => {
    if (subArr === undefined || subArr.length === size) {
      subArr = [item];
      arr.push(subArr);
    } else {
      subArr.push(item);
    }

    return {arr, subArr};
  }, {arr: [], subArr: undefined}).arr;
};

// === sample 2.1 ===
// Here's the same function as sample 2 using a loop
const chunk = (input, size) => {
  const arr = [];
  let subArr = [];
  for (item of input) {
    if (arr.length === 0 || subArr.length === size) {
      subArr = [item];
      arr.push(subArr);
    } else {
      subArr.push(item);
    }
  }
  return arr;
};

// === sample 3 ===
// Here's a mathy version. I'm not a fan since it's harder to explain this in a
// simple way.
function chunk(input, size) {
  var arr = [];
  for (var idx = 0; idx < input.length; idx++) {
    var item = input[idx];
    var newIdx = Math.floor(idx / size);
    var newSubIdx = idx - newIdx * size;

    if (idx % size === 0) arr[newIdx] = [];
       arr[newIdx][newSubIdx] = item;
  }
  return arr;
}

I think my favorite is sample 1.3 since it avoids mutable data and is clear to me. Which function would you use? Would you make your own?

Edit: I had a mistake in my initial code when I didn't handle when arr.length === 0 in this code arr.length === 0 || subArr.length === size. This makes the samples slightly less nice, but still relatively clear in my opinion.

Top comments (0)