Mikelgo
Mikelgo

Reputation: 575

JavaScript array.filter() and iterator

got a array of objects and need to filter this by 2 criterias. One of those criterias is an index counting up.

let data = 
[{"hour": 1, "dayIndex": 0, "value": "something"},
{"hour": 1, "dayIndex": 1, "value": "something"},
{"hour": 1, "dayIndex": 3, "value": "something"},
{"hour": 2, "dayIndex": 0, "value": "something"},
{"hour": 2, "dayIndex": 1, "value": "something"},
// and so on 
]

I need an array of objects filtered by "hour" and ascending "dayIndex" and it is important that for missing dayIndexes an empty object is created. So for hour=1 I would need this:

 let hourOneArray = 
 [
  {"hour" : 1, "dayIndex": 0, "value": "something"},
  {"hour" : 1, "dayIndex": 1, "value": "something"},
  {}, //empty because dayIndex 2 is missing
  {"hour" : 1, "dayIndex": 3, "value": "something"},
  {}, //empty because dayIndex 4 is missing
 ]

My approach was:

   for(let i = 0; i < 4; ++i){
       hourOneArray = data.filter((arg) => {
           return ((arg.hour === 1) && (arg.dayIndex === i));
       })
   } 

Thanks in advance

Upvotes: 2

Views: 3010

Answers (4)

Eddie D
Eddie D

Reputation: 1120

Here's a quick and clean solution to filter all of them by hour, filling in blank days. Make use of map and reduce :D

let data = 
[{"hour": 1, "dayIndex": 0, "value": "something"},
{"hour": 1, "dayIndex": 1, "value": "something"},
{"hour": 1, "dayIndex": 3, "value": "something"},
{"hour": 2, "dayIndex": 0, "value": "something"},
{"hour": 2, "dayIndex": 1, "value": "something"},
// and so on 
]


let defaultArr = [];
data.forEach(val => defaultArr.push({}));


let output = data.reduce((hash, val) => {

  let hour = val.hour;
  let dayIndex = val.dayIndex;

  if(!hash[hour]) hash[hour] = defaultArr.map(val => val);
  hash[hour][dayIndex] = val;
  return hash;
}, {})
console.log(output);

Upvotes: 2

Nikhil Aggarwal
Nikhil Aggarwal

Reputation: 28455

You can try following

let data = [{"hour": 1, "dayIndex": 0, "value": "something"},{"hour": 1, "dayIndex": 1, "value": "something"},{"hour": 2, "dayIndex": 0, "value": "something"},{"hour": 2, "dayIndex": 1, "value": "something"},{"hour": 1, "dayIndex": 3, "value": "something"}];

// Sort the array by hour and dayIndex
data.sort((a,b) => a.hour - b.hour || a.dayIndex - b.dayIndex);

function getHourData(hour) {
  // Get the hour data
  var hourData = data.filter((a) => a.hour === hour);
  // Now, iterate till the maximum dayIndex of the filtered array
  for (let i = 0; i < hourData[hourData.length -1].dayIndex; i++) {
   // If the index is different from dayIndex, count it as missing and add it to the array
   if(i !== hourData[i].dayIndex) hourData.splice(i,0, {});
  }
  // return result
  return hourData;
}

console.log(getHourData(1));

Upvotes: 1

CertainPerformance
CertainPerformance

Reputation: 370689

You can reduce into an object indexed by dayIndex, then add the objects for each missing day, no sorting needed (O(n)):

const input = 
[{"hour": 1, "dayIndex": 0, "value": "something"},
{"hour": 1, "dayIndex": 1, "value": "something"},
{"hour": 1, "dayIndex": 3, "value": "something"},
{"hour": 2, "dayIndex": 0, "value": "something"},
{"hour": 2, "dayIndex": 1, "value": "something"},
];

const [groupedByDay, haveDays] = input
  .reduce(([groupedByDay, haveDays], item) => {
    const { hour, dayIndex } = item;
    if (hour === 1 && !groupedByDay[dayIndex]) {
      groupedByDay[dayIndex] = item;
      haveDays.push(dayIndex);
    }
    return [groupedByDay, haveDays];
  }, [{}, []]);
const length = Math.max(...haveDays) + 1;
const hourOneArray = Array.from({ length }, (_, i) => (
  groupedByDay[i] ? groupedByDay[i] : {}
));
console.log(hourOneArray);

Upvotes: 0

Nishant Dixit
Nishant Dixit

Reputation: 5522

let data = 
[{"hour": 1, "dayIndex": 0, "value": "something"},
{"hour": 1, "dayIndex": 1, "value": "something"},
{"hour": 1, "dayIndex": 3, "value": "something"},
{"hour": 2, "dayIndex": 0, "value": "something"},
{"hour": 2, "dayIndex": 1, "value": "something"}]

data= data.sort((a,b)=>a.dayIndex-b.dayIndex);

data = data.map(val=>val.hour == 1?val:{});

console.log(data);

Upvotes: 0

Related Questions