Home > Mobile >  Filling an array of objects to create consecutive keys
Filling an array of objects to create consecutive keys

Time:09-06

I want to create a heatmap depending on the markers for a given year. I start from an array that looks like this:

[{ 
  year: -400;
  markers: 3;
},
{ 
  year: -330;
  markers: 10;
},
{ 
  year: -20;
  markers: 32;
},
...
{ 
  year: 103;
  markers: 11;
}
...
]

So how could I fill the array with consecutive years from the beginning (-400) to the current year (2022) with markers at 0?

[{ 
  year: -400;
  markers: 3;
},
{ 
  year: -339;
  markers: 0;
},
{ 
  year: -338;
  markers: 0;
},
...
{ 
  year: -330;
  markers: 10;
},
...
{ 
  year: 2021;
  markers: 0;
},
{ 
  year: 2022;
  markers: 0;
}
]

The point is to get a final array of hex depending on the number of markers of each year to use it on a gradient CSS background.

['#DEDEDE', '#F9DB88', ..., '#DEDEDE'...]

CodePudding user response:

In order not to run through the array thousands of times looking for values, I suggest creating a dictionary:

const arr = [
  { 
    year: -400,
    markers: 3,
  },
  ...
];
const dict = Object.fromEntries(arr.map((a) => [a.year, a.markers]));
let result = [];
const currentYear = new Date().getFullYear();
for (let i = -400; i <= currentYear; i  ) {
  result.push({
    year: i,
    markers: dict[i] ?? 0,
  });
}

CodePudding user response:

Use a for loop and push the unknown values!

const arr = [{ 
  year: -400,
  markers: 3,
},
{ 
  year: -330,
  markers: 10,
},
{ 
  year: -20,
  markers: 32,
},
{ 
  year: 103,
  markers: 11,
}
];
let output = [];
const currentYear = (new Date()).getFullYear();
for(let i = -400; i <= currentYear; i  ) {
  const found = arr.find(x => x.year === i);
  if(found) {
    output.push(found);
  } else {
    output.push({
      year: i,
      markers: 0,
    });
  }
}
console.log(output);

CodePudding user response:

Try like below. Explanation is in comment.

let data = [{
    year: -400,
    markers: 3,
  },
  {
    year: -330,
    markers: 10,
  },
  {
    year: -20,
    markers: 32,
  },
  {
    year: 103,
    markers: 11,
  }
];

// variable for result array
let result = [];
// loop over years
for (let year = -400; year <= 2022; year  ) {
  // filter your data and check if marker exist for selected year
  let arr = data.filter(d => d.year == year);
  // if exists then push that value else add new object with marker = 0
  if (arr.length > 0)
    result.push(arr[0]);
  else
    result.push({
      year: year,
      markers: 0
    });
}

console.log(result);

CodePudding user response:

You can first create an placeholder array and then start to replace the values

// start with those years
const start = [{
    year: -400,
    markers: 3,
  },
  {
    year: -330,
    markers: 10,
  },
  {
    year: -20,
    markers: 32,
  },
  {
    year: 103,
    markers: 11,
  }
];

// your first and last year
const firstYear = start[0].year;
const lastYear = start[start.length - 1].year;

// calculate the timespan between the years
const years = lastYear - firstYear;


// build an empty array with markers as 0
const res = Array.from({
  length: years
}).map((_, i) => ({
  year: firstYear   i,
  markers: 0
}));


// replace the years that you have a value for
const yearNumbers = res.map(year => year.year);
for (let existing of start) {
  const overwrite = yearNumbers.indexOf(existing.year);
  if (overwrite === -1) {
    break;
  }

  res[overwrite] = existing;
}


console.log(res)

CodePudding user response:

You might not actually need to fill in your initial array with the missing values. You could do something like this (it's more efficient from a memory point of view and depending on how you use this data, it might be at least ok from a processing time point of view also):

let data = [
  {
    year: -400,
    markers: 3,
  },
  {
    year: -399,
    markers: 10,
  },
  {
    year: -396,
    markers: 10,
  },
];

let availableYears = [];

data.forEach((obj) => availableYears.push(obj.year));

const startYear = data[0].year;
const endYear = data[data.length - 1].year;

for (year = startYear; year <= endYear; year  ) {
  if (!availableYears.includes(year)) {

  /*Here you would use however you want the fact that 
  you know that the markers for this year are missing.
  For the purpose of this example, I just logged the value
  you would have inserted in the array with your approach*/

    console.log({
      year,
      markers: 0,
    });
  }
}

This approach could be a lot more efficient especially for a sparse data array (one with a lot of missing years).

A stackblitz example: https://stackblitz.com/edit/js-1bsmeh?file=index.js

  • Related