viviet
viviet

Reputation: 82

How could I separate each JSON object and group them to an array in JavaScript?

example of req.files from multer.js

[
    {
        fieldname: files0,
        originalname: 'Screenshot from 2020-05-23 01-52-30.png',
        encoding: '7bit',
        mimetype: 'image/png',
        destination: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133',
        filename: '1606822252923_Screenshot from 2020-05-23 01-52-30.png',
        path: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133/1606822252923_Screenshot from 2020-05-23 01-52-30.png',
        size: 172092
      },
      {
        fieldname: files0,
        originalname: 'Screenshot from 2020-05-22 08-44-05.png',
        encoding: '7bit',
        mimetype: 'image/png',
        destination: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133',
        filename: '1606822252925_Screenshot from 2020-05-22 08-44-05.png',
        path: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133/1606822252925_Screenshot from 2020-05-22 08-44-05.png',
        size: 440592
      },
      {
        fieldname: files1,
        originalname: 'Screenshot from 2020-05-30 11-36-42.png',
        encoding: '7bit',
        mimetype: 'image/png',
        destination: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133',
        filename: '1606822252930_Screenshot from 2020-05-30 11-36-42.png',
        path: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133/1606822252930_Screenshot from 2020-05-30 11-36-42.png',
        size: 477511
      },
      {
        fieldname: files1,
        originalname: 'Screenshot from 2020-05-30 11-36-36.png',
        encoding: '7bit',
        mimetype: 'image/png',
        destination: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133',
        filename: '1606822252931_Screenshot from 2020-05-30 11-36-36.png',
        path: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133/1606822252931_Screenshot from 2020-05-30 11-36-36.png',
        size: 223362
      },
      {
        fieldname: files1,
        originalname: 'Screenshot from 2020-05-30 11-36-31.png',
        encoding: '7bit',
        mimetype: 'image/png',
        destination: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133',
        filename: '1606822252932_Screenshot from 2020-05-30 11-36-31.png',
        path: 'public/uploads/projects/0a480789-eb14-4fe4-bb89-44aa741efe33/proposals/chma00000133/1606822252932_Screenshot from 2020-05-30 11-36-31.png',
        size: 260419
      }
]

I want to dynamically group each JSON objects with their fieldname and store them in an array of objects while using their fieldname number as their array index.

The groups can be between 0 to 9, depending on the user input.

The result I'm hoping for is something like

someArr = [

    [
        {
            fieldname: files0
            originalname: somevalue,
            ...
            size: some value
        },
        {
            fieldname: files0,
            originalname: somevalue,
            ...
            size: some value
        },
    ]
        ,
    [
        
        {
            fieldname: files1,
            originalname: somevalue,
            ...
            size: some value
        },
        {
            fieldname: files1,
            originalname: somevalue,
            ...
            size: some value
        },
        {
            fieldname: files1,
            originalname: somevalue,
            ...
            size: some value
        },
    ]
    ...
    
]

and if it exists, someArr[9] would return

[

    {
        fieldname: files9,
        originalname: somevalue,
        ...
        size: some value
    },
    {
        fieldname: files9,
        originalname: somevalue,
        ...
        size: some value
    },
]

What I've tried was first parse integers from fieldnames and reassign them as their values for better sorting with for-loops

Object.keys(req.files).forEach((key) => {
  const thisFile = req.files[key];
  const thisFileGroup = parseInt(thisFile.fieldname.match(/\d/g).join(''), 10); 
  // rename fieldname from files0, files1 ... to 0 , 1 ....
  req.files[key].fieldname = thisFileGroup;
});

But from here, I can't find where to push this element(thisFile) to, since I cannot predeclare each arrays at the upper scope since they also need to be created dynamically.

Upvotes: 1

Views: 748

Answers (3)

Jack Yu
Jack Yu

Reputation: 2425

I try to not modify your logic to do that.
If there is no files2, filesArray[2] will be undefined.

// Omit other fields
const req = {
    files: [
        { fieldname: "files0", originalname: 'Screenshot from 2020-05-23 01-52-30.png'},
        { fieldname: "files0", originalname: 'Screenshot from 2020-05-22 08-44-05.png'},
        { fieldname: "files1", originalname: 'Screenshot from 2020-05-30 11-36-42.png'},
        { fieldname: "files1", originalname: 'Screenshot from 2020-05-30 11-36-36.png'},
        { fieldname: "files1", originalname: 'Screenshot from 2020-05-30 11-36-31.png'},
        { fieldname: "files3", originalname: 'Screenshot from 2020-05-30 11-36-42.png'},
        { fieldname: "files3", originalname: 'Screenshot from 2020-05-30 11-36-36.png'},
        { fieldname: "files3", originalname: 'Screenshot from 2020-05-30 11-36-31.png'}
    ]
}

let filesArray = []

for (let file of req.files) {
    const thisFileGroup = parseInt(file.fieldname.match(/\d/g).join(''), 10);
    if (!filesArray[thisFileGroup]) {
        filesArray[thisFileGroup] = []
    }
    filesArray[thisFileGroup].push(file)
}

console.log(filesArray[2]) // will be undefined
console.log(filesArray[1]) // will be files1 array
console.log(filesArray)

Upvotes: 1

mplungjan
mplungjan

Reputation: 177955

I would use reduce

const data = [ 
{ fieldname: 'files0', originalname: 'Screenshot from 2020-05-23 01-52-30.png', },
{ fieldname: 'files0', originalname: 'Screenshot from 2020-05-22 08-44-05.png', },
{ fieldname: 'files1', originalname: 'Screenshot from 2020-05-30 11-36-42.png', },
{ fieldname: 'files1', originalname: 'Screenshot from 2020-05-30 11-36-36.png', },
{ fieldname: 'files1', originalname: 'Screenshot from 2020-05-30 11-36-31.png', }],
arr = data.reduce((acc, cur) => {
  const idx = cur.fieldname.replace("files",""); // get 0, 1
  if (acc[idx]) acc[idx].push(cur); // if already there, just push
  else acc[idx] = [cur];            // otherwise initialise
  return acc;
},[]) 

console.log(arr)

NOTE: The groups can be between 0 to 9, depending on the user input.

I assume there are no holes since that could result in a sparse array so

data = [ 
     { fieldname : 'files0' },
     { fieldname : 'files0' },
     { fieldname : 'files3' },
     { fieldname : 'files3' },
 }

would create an array of

[
  [ { fieldname : 'files0' }, { fieldname : 'files0' } ],
  null,
  null,
  [ { fieldname : 'files3' }, { fieldname : 'files3' } ],
]

Upvotes: 3

Roko C. Buljan
Roko C. Buljan

Reputation: 206121

If you don't need necessarily an order by index files[index]

you could in that case Array.prototype.reduce() to Object.
Your object will be grouped by fieldname properties (not by alphabetical order though) containing one array with the items having that same property key.
Iterate your object using Object.values() (and Array.prototype.forEach() if needed).

const data = [
  { fieldname: "files0", originalname: '0-a'},
  { fieldname: "files0", originalname: '0-b'},
  { fieldname: "files1", originalname: '1-a'},
  { fieldname: "files1", originalname: '1-b'},
  { fieldname: "files1", originalname: '1-c'},
];

const byFieldName = data.reduce((ob, d) => {
  if (!ob.hasOwnProperty(d.fieldname)) ob[d.fieldname] = [];
  ob[d.fieldname].push(d);
  return ob;
}, {});

// console.log(byFieldName); // Uncomment to see how it looks like
console.log( Object.values(byFieldName) );

Upvotes: 1

Related Questions