4

This is the initial state.

const All = { 
  id : [ "a", "b", "c", "d", "e"],
  count : [1, 2, 2],
}

I want All.id split into [ ["a"], ["b", "c"], ["d", "e"]] by using the All.count

I tried R.map(R.take(All.count), All.id). But this is not working.

What I am missing here?

Rio
  • 123
  • 7

2 Answers2

4

You can use R.mapAccum to slice the section between the current and previous position, and to preserve the previous position in the accumulator. Use R.last to take the resulting array (the 1st item is the accumulator).

const { pipe, mapAccum, slice, last } = R

const fn = ({ id, count }) => pipe(
  mapAccum((acc, v) => [acc + v, slice(acc, acc + v, id)], 0),
  last
)(count)

const All = { id : [ "a", "b", "c", "d", "e"], count : [1, 2, 2] }

const result = fn(All)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous"></script>
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
4

While I'm sure we could do this with Ramda, the first thing that comes to mind is a simple recursive call:

const groups = ([n, ...ns], xs) =>
  n == undefined || xs .length == 0
    ? []
    : [xs .slice (0, n), ... groups (ns, xs .slice (n))]

const All = {id : [ "a", "b", "c", "d", "e"], count : [1, 2, 2]}

console .log (groups (All.count, All.id))

We simply take the first group off the top and then recursively call with the remainder of the array and a smaller list of counts.

I originally wrote R .take (n) and R .drop (n) in place of the two .slice calls, and would use it that way if I was already using Ramda. But it's fairly clean as is.

Update

An alternate technique might look like this:

const groups = (ns, xs) =>
  ns.reduce(({xs, found}, n) => ({
    xs: xs.slice(n), 
    found: [...found, xs.slice(0, n)]
  }), {xs, found: []}).found
Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103