csharpdev
csharpdev

Reputation: 31

Split array of strings into more arrays of strings?

Hello so what I want to do is split array of names into more arrays of names and each arrays element joined together should be smaller than specific amount of characters and none of the strings should be split in half. if it needs to be split in half then move it to the next array. so an example would be.

Input: arr: ["george","ben","bob","alex","robert"] amount_of_characters: 10

Output: [["george","ben"],["bob","alex"],["robert"]]

Upvotes: 2

Views: 97

Answers (7)

MWO
MWO

Reputation: 2806

Another way of writing it using Array.reduce():

const input = ["george","ben","bob","alex","Robert"];

let idx=0;

const output = (amount_of_characters)=>{
    return input.reduce((acc,curr)=>{
        acc[idx]?null: acc.push([]);
        acc[idx].join('').length + curr.length <= amount_of_characters? 
        acc[idx].push(curr):(idx++, acc.push([]), acc[idx].push(curr)); 
        return acc;
    },[])
}

console.log(output(10));

Upvotes: 0

zitzennuggler
zitzennuggler

Reputation: 106

const foo = function (arr, max) { // arr - input, max - max characters in one array
const result = [];
for (let i = 0; i < arr.length; i++) {
    let cur = [];
    if (arr[i].length < max && i !== arr.length - 1) {
        let sum = arr[i].length;
        cur.push(arr[i]);
        while (sum <= max) {
            i++;
            if (arr[i].length + sum <= max) {
                sum += arr[i].length;
                cur.push(arr[i]);
            } else {
                sum = max + 1;
                i--;
            }
        }
    } else cur.push(arr[i]);
    result.push(cur);
}
return result;

};

Upvotes: 0

jsN00b
jsN00b

Reputation: 3691

So, what is required here is an algorithm to achieve the expected result. While multiple answers above have given elegant solutions, the below solutions use a recursive approach.

Solution - Style-1:

const joinUptoLen1 = (arr = [], mlen, i = 0) => (
  i < arr.length - 1 ?
  arr[i].length + arr[i + 1].length < mlen ?
  [
    [arr[i], arr[i + 1]]
  ].concat(joinUptoLen1(arr, mlen, i + 2)) :
  [
    [arr[i]]
  ].concat(joinUptoLen1(arr, mlen, i + 1)) :
  i === arr.length - 1 ?
  [
    [arr[i]]
  ] :
  []
);

The same solution written another way is shown below:

Solution - Style-2:

const joinUptoLen2 = (arr = [], mlen, i = 0) => {
  if (i < arr.length - 1) {
    if (arr[i].length + arr[i + 1].length < mlen) {
      return [
        [arr[i], arr[i + 1]]
      ].concat(joinUptoLen2(arr, mlen, i + 2));
    } else {
      return [
        [arr[i]]
      ].concat(joinUptoLen2(arr, mlen, i + 1));
    }
  } else {
    if (i === arr.length - 1) return [
      [arr[i]]
    ];
    return [];
  }
};

Approach is very simple. Check if sum-of-lengths of 2 consequent array-elements is lesser than the input-length. If so, make an array of the 2 elements and push this new-array into the result-array. If not, push an array with just the one element into the result-array. Recursively follow the same and handle the edge-scenario (if the last element was not included into a pair).

And here's a code snippet for quick-demo:

const inpArr1 = ["george", "ben", "bob", "alex", "robert"];
const inpArr2 = ["george", "ben", "bob", "alex", "robert", "pat"];
const splitLen = 10;

const joinUptoLen1 = (arr = [], mlen, i = 0) => (
  i < arr.length - 1 ?
  arr[i].length + arr[i + 1].length < mlen ? [
    [arr[i], arr[i + 1]]
  ].concat(joinUptoLen1(arr, mlen, i + 2)) : [
    [arr[i]]
  ].concat(joinUptoLen1(arr, mlen, i + 1)) :
  i === arr.length - 1 ? [
    [arr[i]]
  ] : []
);

const joinUptoLen2 = (arr = [], mlen, i = 0) => {
  if (i < arr.length - 1) {
    if (arr[i].length + arr[i + 1].length < mlen) {
      return [
        [arr[i], arr[i + 1]]
      ].concat(joinUptoLen2(arr, mlen, i + 2));
    } else {
      return [
        [arr[i]]
      ].concat(joinUptoLen2(arr, mlen, i + 1));
    }
  } else {
    if (i === arr.length - 1) return [
      [arr[i]]
    ];
    return [];
  }
};

console.log('style-1 results: ', joinUptoLen1(inpArr1, splitLen));
console.log('style-2 results: ', joinUptoLen2(inpArr1, splitLen));

Upvotes: 0

Sash Sinha
Sash Sinha

Reputation: 22350

You could use a for-of loop and access the last element of the current group using Array.prototype.at():

const groupByUpToNCharacters = (arr, n) => {
    const groups = [[]];
    let currGroupLength = 0;
    for (const word of arr) {
        const wordLength = word.length;
        if (currGroupLength + wordLength <= n) {
            groups.at(-1).push(word);
            currGroupLength += wordLength;
        } else {
            groups.push([word]);
            currGroupLength = wordLength;
        }
    }
    return groups;
}


const arr = ["george", "ben", "bob", "alex", "robert"];
const groupedArr = groupByUpToNCharacters(arr, 10);
console.log(groupedArr);

Upvotes: 0

shidoro
shidoro

Reputation: 370

const arr = ["george","ben","bob","alex","robert"];
const amount_of_characters = 10;
const result = [];
let sumChars = 0;

for (let i = 0; i < arr.length; i++) {
  const word = arr[i];
  
  if (word.length + sumChars > amount_of_characters) {
    result.push([word])
    sumChars = 0;
  }
  else {
    !result.length ? result.push([word]) : result[result.length - 1].push(word);
  }
  
  sumChars += word.length;
};

console.log(result);

Upvotes: 1

Shift and Shiftine
Shift and Shiftine

Reputation: 181

function split(arr, amount_of_characters){
  let final_arr = [];
  let i = 0; // This will be used to denote which position on the original array should be filled
  let j = 0; // This will be used to denote which position on the final array should be filled
  while (i < arr.length){
    // Create a new array in the array
    final_arr[j] = [];
    let current_character_count = 0;

    // Iterate over the input array
    while (i < arr.length && arr[i].length + current_character_count < amount_of_characters){
      final_arr[j].push(arr[i]);
      current_character_count += arr[i].length;
      i++;
    }
    j++;
  }
}

Upvotes: 0

DecPK
DecPK

Reputation: 25408

You can easily achieve the result as:

const arr = ['george', 'ben', 'bob', 'alex', 'robert'];
const amount_of_characters = 10;

let currentTotal = 0;
const result = [];

for (let i = 0; i < arr.length; i++) {
  const curr = arr[i];
  if (currentTotal + curr.length <= amount_of_characters) {
    currentTotal += curr.length;
    const last = result[result.length - 1];
    !last ? result.push([curr]) : result[result.length - 1].push(curr);
  } else {
    currentTotal = 0;
    result.push([]);
    i--;
  }
}

console.log(result);

Upvotes: 0

Related Questions