1

I am unable to modify JSON file. Tried to use all my knowledge of loops (map,filter) and conditions(if,else) JavaScript. But nothing comes out. Please tell me how to make such a file from this file

[{
    "model": "2002R \"Protection Pack - Mirage Grey",
    "img": "2002r-protection-pack-mirage-grey.jpg"
  },
  {
    "model": "2002R \"Protection Pack - Mirage Grey",
    "img": "2002r-protection-pack-mirage-grey-2.jpg"
  },
  {
    "model": "550 \"White Black",
    "img": "BB550HA1-2.jpg"
  },
  {
    "model": "550 \"White Black",
    "img": "BB550HA1-3.jpg"
  },]

Should be like this

   [{
    "model": "2002R \"Protection Pack - Mirage Grey",
    "img": ["2002r-protection-pack-mirage-grey.jpg", "2002r-protection-pack-mirage-grey-2.jpg"]
  },
  {
    "model": "550 \"White Black",
    "img": ["BB550HA1-2.jpg","BB550HA1-3.jpg"]
  },
]

I tried this. But no correct result.

let modelsArray = [];
let prevModel = '';
let currentModel = '';
let pictureArray = [];
let counterModel = 0;

fs.readFile(path, 'utf-8', (err, data) => {
  if (err) console.log(err.message);

  try {
    const dataArr = JSON.parse(data);

    const newArr = dataArr.map((item, ind) => {
      currentModel = item.model;

      pictureArray.push(item['img']);

      if (modelsArray.length == 0) {
        modelsArray[counterModel] = { model: item.model };
        prevModel = currentModel;
      }

      if (prevModel !== item.model) {
        counterModel++;
        modelsArray[counterModel] = { model: item.model };
      }

      prevModel = currentModel;


      
    });

Please give me advice

Alexander Nenashev
  • 8,775
  • 2
  • 6
  • 17
SharpLon
  • 15
  • 6

2 Answers2

0

Array::reduce is a good option to collect data from an array. Here we have an accumulator of the result array and a map where we can easily find already added models to add images to them:

r.map.get(model)?.img.push(img)

if a model isn't found add it to both the array and the map:

r.map.set(model, r.arr[r.arr.length] = {model, img: [img]});

const models = [{
    "model": "2002R \"Protection Pack - Mirage Grey",
    "img": "2002r-protection-pack-mirage-grey.jpg",
    "brand": "test brand"
  },
  {
    "model": "2002R \"Protection Pack - Mirage Grey",
    "img": "2002r-protection-pack-mirage-grey-2.jpg"
  },
  {
    "model": "550 \"White Black",
    "img": "BB550HA1-2.jpg"
  },
  {
    "model": "550 \"White Black",
    "img": "BB550HA1-3.jpg"
  },];
  
const images = models.reduce((r, {model, img, ...props}) => {
  r.map.get(model)?.img.push(img) ?? 
  r.map.set(model, r.arr[r.arr.length] = {model, img: [img], ...props});
  return r;
}, {arr: [], map: new Map}).arr;

console.log(images);
Alexander Nenashev
  • 8,775
  • 2
  • 6
  • 17
  • One more question please. What if i have not only 2 fields in models. { "model": "2002R \"Protection Pack - Mirage Grey", "brand": "New Balance", "img": "2002r-protection-pack-mirage-grey.jpg" },{ "model": "2002R \"Protection Pack - Mirage Grey", "brand": "New Balance", "img": "2002r-protection-pack-mirage-grey-2.jpg" } How should i change map? – SharpLon Jul 05 '23 at 10:34
  • 1
    @SharpLon use `...props` to collect the rest of properties, updated the answer – Alexander Nenashev Jul 05 '23 at 10:36
  • @SharpLon it's the spread syntax, learn here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax – Alexander Nenashev Jul 05 '23 at 10:40
  • Thank you. Should i use spread syntax, after when reduce method finished work ? – SharpLon Jul 05 '23 at 10:46
  • @SharpLon i dont understand your quesiton, but, yes, you could use the spread syntax in your JS code, it's a modern feature of JS – Alexander Nenashev Jul 05 '23 at 10:51
  • I meant should I use the spread operator after the reduce method is done? Or insert the values ​​into the array with three and more fields during the loop? – SharpLon Jul 05 '23 at 14:41
  • @SharpLon `...props` will handle any number of extra props, no need to modify the code – Alexander Nenashev Jul 05 '23 at 15:04
  • @SharpLon btw you have 15 reputation now and can upvote my answer (the arrow up). that way i'll be rewarded 10 points and will be motivated to help you in the future, thanks! – Alexander Nenashev Jul 05 '23 at 16:28
0

Since you expect the model property to be unique, I'd just use either a Map or Object-like-a-Map for this:

const data = /* original dataset here */;
const output = {};

for (const item of data) {
  output[item.model] = output[item.model] || [];
  output[item.model].push(item.img);
}

If you want to reformat that output back to an Array, you could use Object.entries():

[...Object.entries(output)].map([model, img] => { model, img });
Brad
  • 159,648
  • 54
  • 349
  • 530