-4

I have two arrays a and b.
Either array can have any number of items. However their length may not match.

I need the array lengths to match so I can zip the two array together.

For example:
a = [1, 2, 3, 4] and b = [1, 2]

Becomes:
a = [1, 2, 3, 4] and b = [1, 1, 2, 2]

I need b to match the length of a or vice versa to whatever one is longer length.
As well as to spread the values of the shorter array until matches the length of the longer array.

The spread on the shorter array would only contain the values present at start.

For example: a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and b = [1, 2]

Becomes a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and b = [1, 1, 1, 1, 1, 2, 2, 2, 2, 2]

Another example:
a = [21, 22, 23, 24, 25, 26, 27] and b = [39, 40, 41, 42]

Becomes:
a = [21, 22, 23, 24, 25, 26, 27] and b = [39, 39, 40, 40, 41, 41, 42]

SOLVED IT using Ramda

const a = [1, 2] const b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

R.sort(R.gte, R.flatten(R.repeat(a, b.length / 2)))

Tristan Forward
  • 3,304
  • 7
  • 35
  • 41
  • What is the logic for expanding the shorter array? What happens if the longer is `[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]` and the shorter is `[1, 2]`? – VLAZ Apr 02 '20 at 00:49
  • You should explain HOW you want to spread them, but I'm almost 100% positive you do something really quirky. – Robo Robok Apr 02 '20 at 00:50
  • @VLAZ I need to zip the two arrays into pairs [1, 2]. For your example it would just be [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and [1, 1, 1, 1, 1, 2, ,2 ,2, 2, 2] – Tristan Forward Apr 02 '20 at 00:52
  • @TristanForward ok, I was initially thinking of something [like this](https://stackoverflow.com/a/59410094/) but it's probably even simpler. You just need to repeat each item in the shorter array. – VLAZ Apr 02 '20 at 00:55
  • 1
    @VLAZ Thanks your right solved it using Ramda const a = [1, 2] const b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] R.sort(R.gte, R.flatten(R.repeat(a, b.length / 2))) – Tristan Forward Apr 02 '20 at 01:45
  • 1
    @TristanForward [just in case you're interested in a pure JS solution](https://jsbin.com/tayamolaci/1/edit?js,console) – VLAZ Apr 02 '20 at 01:57

2 Answers2

0

Without relying on any libraries, this function will give you the desired result

const a = [21, 22, 23, 24, 25, 26, 27]
const b = [39, 40, 41, 42]

// a, b = longer array, shorter array
function spread(a, b) {
  let result = null
  if (a.length !== b.length) {
    // target: array that needs to be spread
    const [target, longest] = a.length > b.length ? [b, a] : [a, b]
    // difference: amount target needs to be spread
    const difference = longest.length - target.length
    // check if elements need to be repeated more than twice
    if (difference > target.length) {
      result = [].concat(
        ...target.map((n, i) => {
          if (typeof n !== 'string') {
            return Array.from(n.toString().repeat(difference / 2)).map(Number)
          }
          return Array.from(n.repeat(difference / 2))
        })
      )
    } else {
      // repeat N elements twice until N <= difference/2
      result = [].concat(
        ...target.map((n, i) => (i <= difference / 2 ? [n, n] : n))
      )
    }
    // return the spread array
    return result
  }
  // return original array if both arrays are same length
  return b
}

spread(a, b) // => [ 39, 39, 40, 40, 41, 42 ] 
Brendan C.
  • 171
  • 5
0

Pure JavaScript solution that will extend a shorter array to the length of a longer one. The stretching is done by repeating each value in the shorter array and dynamically re-calculating how many times this is needed. So with lengths 10 and 3, the shorter array will have the first item repeated three times but the rest only two times in order to fit:

longer length: 10

shorter:   [ 1,       2, 3 ]
            /|\      /|  |\
           / | \    / |  | \
result: [ 1, 1, 1, 2, 2, 3, 3 ]

function equaliseLength(a, b) {
  const [shorter, longer] = [a, b].sort((x, y) => x.length - y.length);

  let remaining = longer.length;
  
  const stretchedArray = shorter.flatMap((item, index) => {
    //how many we need of this element
    const repeat = Math.ceil(remaining / (shorter.length - index));
    
    //adjust the remaining
    remaining -= repeat;
    
    //generate an array with the element repeated
    return Array(repeat).fill(item)
  });
  
  //return to the order of the input:
  //if `a` was the longer array, it goes first
  //otherwise flip them
  return longer === a ? 
    [longer, stretchedArray] :
    [stretchedArray, longer]
}


console.log(printResult(
  [1, 2, 3, 4], 
  [1, 2]
));
console.log(printResult(
  [21, 22, 23, 24, 25, 26, 27], 
  [39, 40, 41, 42]
));
console.log(printResult(
  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 
  [1, 2]
));
console.log(printResult(
  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 
  [1, 2, 3]
));
console.log(printResult(
  [1, 2, 3], 
  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
));

console.log(printResult(
  [ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10],
  [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
));

//just to make the display better
function printResult(a, b) {
  const [resultA, resultB] = equaliseLength(a, b)
    .map(x => x.map(y => String(y).padStart(2)))
    .map(x => x.join("|"))
  
  return `a = ${JSON.stringify(a)} b = ${JSON.stringify(b)} 
result:
a = |${resultA}|
b = |${resultB}|`;
}
VLAZ
  • 26,331
  • 9
  • 49
  • 67