Rob Fyffe
Rob Fyffe

Reputation: 729

How to modify an array of objects to group by most recent year?

I currently have an array of objects like so:

const array = [
  { key: 'model_1', year: 2019, displayOrder: 1},
  { key: 'model_1', year: 2018, displayOrder: 2},
  { key: 'model_2', year: 2018, displayOrder: 3},
  { key: 'model_3', year: 2018, displayOrder: 4},
  { key: 'model_4', year: 2019, displayOrder: 5},
  { key: 'model_5', year: 2018, displayOrder: 6},
];

I am trying to generate a new array that groups the objects by current and previous year and orders by displayOrder. If we applied this to the above array it would look like this:

const array = {
  current: [
    { key: 'model_1', year: 2019, displayOrder: 1 },
    { key: 'model_2', year: 2018, displayOrder: 3 },
    { key: 'model_3', year: 2018, displayOrder: 4 },
    { key: 'model_4', year: 2019, displayOrder: 5 },
    { key: 'model_5', year: 2018, displayOrder: 6 },
  ],
  previous: [
    { key: 'model_1', year: 2018, displayOrder: 2 },
    { key: 'model_4', year: 2018, displayOrder: 7 },
  ],
};

The theory behind this is that it should show the current version of the model. That will be based on the most recent year for the model.

I have attempted this by creating a reducing function that groups them by year, but I don't think this is the right approach as there could be a lot of overhead than to modify this further.

const modelsByYear = array.reduce((acc, model) => {
  acc[model.year] = acc[model.year] || [];
  acc[model.year].push(model);
  return acc;
}, Object.create(null));

What are some suggestions on how I can do this?

EDIT:

The reason I need this is for filtering. If I click on current or previous I need to see the respective models.

Upvotes: 2

Views: 85

Answers (2)

Nina Scholz
Nina Scholz

Reputation: 386660

You could check the key and splice ither the current array or push to the previous array.

const array = [{ key: 'model_1', year: 2019, displayOrder: 1 }, { key: 'model_1', year: 2018, displayOrder: 2 }, { key: 'model_2', year: 2018, displayOrder: 3 }, { key: 'model_3', year: 2018, displayOrder: 4 }, { key: 'model_4', year: 2019, displayOrder: 5 }, { key: 'model_5', year: 2018, displayOrder: 6 }, { key: 'model_4', year: 2018, displayOrder: 7 }],
    grouped = array.reduce((r, o) => {
        var index = r.current.findIndex(({ key }) => o.key === key);
        if (index !== -1) {
            if (r.current[index].year > o.year) {
                r.previous.push(o);
                return r;
            }
            r.previous.push(r.current.splice(index, 1)[0]);
        }
        r.current.push(o);
        return r;
    }, { current: [], previous: [] });

console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 2

amrender singh
amrender singh

Reputation: 8239

Considering there is a typo in output, i.e

{ key: 'model_5', year: 2018, displayOrder: 6 }

Should be present in current(as per comment of op). You can try the following:

Sort the array based on key in descending order , year in ascending order and display order in ascending order. After that you can simply iterate over the list and get the desired result. Try the following:

const array = [
  { key: 'model_1', year: 2019, displayOrder: 1},
  { key: 'model_1', year: 2018, displayOrder: 2},
  { key: 'model_2', year: 2018, displayOrder: 3},
  { key: 'model_3', year: 2018, displayOrder: 4},
  { key: 'model_4', year: 2019, displayOrder: 5},
  { key: 'model_5', year: 2018, displayOrder: 6},
];
array.sort((a,b)=> a.key.localeCompare(b.key) || b.year - a.year|| a.displayOrder - b.displayOrder);

var result = {
  "current" : [],
  "previous" : []
};

for(var i = 0; i < array.length; i++){
  if(i == 0 || result.current[result.current.length-1].key != array[i].key){
    result.current.push(array[i]);
  } else{
    result.previous.push(array[i]);
  }
}
console.log(result);

Upvotes: 0

Related Questions