2

I've got these two arrays and I need to obtain c. I managed to obtain a solution with two fors and conditionals, but I'm sure something better than O^2 can be obtained with JS.

a = [3, 2, 1, 3]
b = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']

c = [['a', 'b', 'c'], ['d', 'e'], ['f'], ['g', 'h', 'i']]
1
  • I don't think you can do something faster. The only thing you could improve is using a declarative approach rather than an imperative one. Commented Apr 7, 2022 at 8:56

4 Answers 4

4

For fun purpose I wrote it in a coincisive way, hope you like it:

const a = [3, 2, 1, 3];
const b = ["a", "b", "c", "d", "e", "f", "g", "h", "i"];
const bClone = [...b];

const array = a.map((num, index) =>
  Array.from({ length: num }, () => bClone.shift())
);

console.log(array);

Of course controls should be added, thanks

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

4 Comments

This solution mutates b, even though b is supposed to be a constant.
Yes I missed that! Thanks for the feedback, so in this case I guess you have to clone b first
What does coincisive mean (in this or a programming context)?
HI phhu, with coincisive I meant coincided, like easy to read. Thanks for pointing out this mistype!
2

I don't have that much good background in algorithms but I think this is better than two fors:

let a = [3, 2, 1, 3]
,b = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']

let head = 0

let result = a.map((e) => {
      let subArr = b.slice(head,head+e)   
      head +=e
      return subArr
  })
  
 console.log(result)

1 Comment

"Suggested edit queue is full", someone else got triggered by indents. Like your solution
2

One possibility is to combine map with splice, taking care not to mutate the original array:

const a = [3, 2, 1, 3];
const b = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'];

function slices(sizes, arr){
  const clonedArr = [].concat(arr);     // clone array to prevent mutation 
  return sizes.map(size => clonedArr.splice(0,size));
}

console.log(slices(a,b));     // [['a', 'b', 'c'], ['d', 'e'], ['f'], ['g', 'h', 'i']]

Alternatively, avoiding mutation altogether, you could use slice with a slightly convoluted reduce:

const slicesByReduce = (sizes, arr) => sizes
  .reduce(({start, acc}, size) => ({
    start: start + size,
    acc: [...acc, arr.slice(start, start + size)]
  }),{
    start: 0,
    acc: []
  }).acc;

console.log(slicesByReduce(a,b));     // [['a', 'b', 'c'], ['d', 'e'], ['f'], ['g', 'h', 'i']]

4 Comments

you don't need to clone an array to use splice. You can use slice instead, which doesn't alter the original array
True, but here I'm relying splice to make the array shorter each time to save tracking the slice start position.... how would you write this function with slice?
by tracking the slice start position.
Good thinking... I've added a slightly ugly reducer to this effect.
1

Iterate your array of "sizes" and get slices of the second array into the result, like this:

const a = [3, 2, 1, 3]
const b = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']

const c = [];
var index = 0;
for (var size of a) {
    c.push(b.slice(index, index + size));
    index += size;
}
  
console.log(c)
//c = [['a', 'b', 'c'], ['d', 'e'], ['f'], ['g', 'h', 'i']]

Also, if you are going to work with arrays in JavaScript, please look into:

  • initializing variables with var, let and const
  • using push()
  • for loops

3 Comments

How is this better than phhu´s solution, which you viewed and commented on before making your solution? If anything, this solution seems more complicated.
Your comment doesn't add anything to the discussion
Your answer doesn't add anything to the answers that already existed before you posted it.

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.