1

Getting the last part of my array manipulation to work is driving me crazy. Essentially I have:

var array1 = [
  ["2", "1007"],
  ["5", "1042"],
  ["3", "1076"],
]

and I want this...

var array2 = [
  ["2", "1007", "1008"],
  ["5", "1042", "1043", "1044", "1045", "1046"],
  ["3", "1076", "1077", "1078"],
]

In other words, I want to use the first element of each sub group as a counter to drive consecutive additions to the second element. It's the latter part I'm stuck on and can't see why my code doesn't work. The fiddle breaks down the operation into simple parts. This will be for around 12,000 rows, so I imagine my current approach with multiple 'forEach' loops is not the fastest. Any ideas on better performance (while still being readable please), would be most welcome.

var array1 = [
  ["2", "1007"],
  ["5", "1042"],
  ["3", "1076"],
]

array2 = []
console.table(array1)

//--------

array1.forEach(e => {
  for (var counter = 0; counter < e[0]; counter++) {
    array2.push(e);
  }
});

console.table(array2);

//--------


var myCol2 = 1007
var mycounter = 0

array2.forEach(e => {

  if (e[1] == myCol2) {
    mycounter = mycounter + 1
    var myinteger = parseInt(e[1]) + mycounter // convert ref. to number
    myinteger = myinteger.toString(); // convert ref. back to string

    e[1] = myinteger
    myCol2 = e[1]
  }
  else
  {
    myCol2 = e[1]
    mycounter = 0
  }

});

console.table(array2);

Fiddle: https://jsfiddle.net/u2fwy6hc/

1
  • array1.map(([n, s]) => [n, ...Array(+n).fill().map((_, i) => `${+s + i}`)]); but note that this will not fulfill your "fastest" requirement, it's just a funny way :) Commented Sep 26, 2019 at 13:09

3 Answers 3

3

Instead of using .forEach(), you could use .map() to convert each inner array to an "expanded" version of itself based on the first value provided in your inner array like so:

const arr = [
  ["2", "1007"],
  ["5", "1042"],
  ["3", "1076"],
];

const res = arr.map(([r, start]) => { // use destructuring to get the first and second element of your inner array
  const ret = []; // create a temp array to hold our "consecutive" integers
  for(let i = +start; i<+start + +r; i++) // create a loop, to loop through our number range (where `i` represents a given number in the range
    ret.push(''+i); // add the number to the temp array (as a string ''+)
  return [r, ret]; // return he new array to take the place of the inner array
});

console.log(res);

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

1 Comment

This is great and explained clearly enough for me to understand. To "convert each inner array to an "expanded" version of itself" is exactly what I was stuck on. Your help much appreciated.
2

For a more compact version, you could use Array.reduce() and some ES6 spreading:

const arr2 = array1.reduce((acc,[count,start])=>{
   const vals = [...Array(+count).keys()].map(val=>`${+start+val}`)
   return [...acc, [`${count}`,...vals]]
 },[])

Which can even be done as a one-liner:

var arr2 = array1.reduce((acc, [count, start])=> [...acc, [`${count}`,...[...Array(+count).keys()].map(val=>`${+start+val}`)]]
,[])

Edit: on reflection, Array.map() is superior:

var arr2 = array1.map(([count, start])=> [count, ...[...Array(+count).keys()].map(val=>`${+start + +val}`)])

Comments

0

You could iterate the array and take the inner array and fill it until the wanted count is reached.

function fill(array) {
    for (let a of array) {
        let [i, v] = a;
        while (--i) a.push((++v).toString());
    }
}

var array1 = [
  ["2", "1007"],
  ["5", "1042"],
  ["3", "1076"],
];

fill(array1);

console.log(array1);

Comments

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.