3

I have array of strings

const arr = ['some', 'word', 'anotherverylongword', 'word', 'yyy', 'u']
const joined = arr.join(';')

I want to get array of chunks where joined string length is not greater than 10

for example output would be:

[
    ['some;word'], // joined string length not greater than 10
    ['anotherverylongword'], // string length greater than 10, so is separated
    ['word;yyy;u'] // joined string length is 10
]
user3075373
  • 44
  • 1
  • 4
  • 19

1 Answers1

3

You can use reduce (with some spread syntax and slice) to generate such chunks:

const arr = ['some', 'word', 'anotherverylongword', 'word', 'yyy', 'u'];
const chunkSize = 10;

const result = arr.slice(1).reduce(
  (acc, cur) =>
    acc[acc.length - 1].length + cur.length + 1 > chunkSize
      ? [...acc, cur]
      : [...acc.slice(0, -1), `${acc[acc.length - 1]};${cur}`],
  [arr[0]]
);

console.log(result);

The idea is building the array with the chunks (result) by starting with the first element from arr (second parameter to reduce function), and then, for each one of the remaining elements of arr (arr.slice(1)), checking if it can be appended to the the last element of the accumulator (acc). The accumulator ultimately becomes the final returning value of reduce, assigned to result.

Alberto Trindade Tavares
  • 10,056
  • 5
  • 38
  • 46
  • Downvoted for bad readability. Using a function body with if / else statements and `push` instead of spread would increase performance and readability. – Wendelin Feb 22 '20 at 15:52
  • Once you truly get the idea of `reduce`, this becomes quite natural. This is in a more functional style (also the idea of not having assignments, using spread operator, etc.). But I do agree that it can be hard to read in the beginning. – Alberto Trindade Tavares Feb 22 '20 at 15:54
  • 1
    I have no problem with reduce but the nested ternary operators. – Wendelin Feb 22 '20 at 15:56
  • I see your point. It's a matter of personal taste, I would say. But I managed to simplify the code a bit in the `slice` usage. – Alberto Trindade Tavares Feb 22 '20 at 15:57
  • 1
    with this solution, if i change `'u'` into `'uu'` it output `[ 'some;word', 'anotherverylongword', 'word;yyy;uu' ]`, and `'word;yyy;uu'` has 11 characters, so is greater than 10, so the `'uu'` should be separated – user3075373 Feb 22 '20 at 15:57
  • 1
    Good observation, @user3075373. There was an off-by-one error. Just edited my answer to fix this. – Alberto Trindade Tavares Feb 22 '20 at 15:58
  • 1
    I'd simplify by starting the accumulator with the first element and reducing the remainder of the array. I'd also try to work in a few upside-down Spanish question marks, just for fun :-) – danh Feb 22 '20 at 16:17
  • @danh I like that haha. Edited my answer a bit ;) – Alberto Trindade Tavares Feb 22 '20 at 16:25