1

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.

2
  • 1
    Please accept @mplungjan 's answer. I missed that you need to order by index 0, 1 etc. Using object is great for grouping, but the final order will not be organized by the keys alphabetical order. Commented Dec 1, 2020 at 13:20
  • 1
    @Roko C. Buljan checked! I will definitely also keep your solution in mind! Commented Dec 1, 2020 at 15:28

3 Answers 3

3

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' } ],
]
Sign up to request clarification or add additional context in comments.

10 Comments

clean and simple!! great answer!! I should look for reduce
@mplungjan yep Got it! No fieldname replace -ing! yey! :P ;)
Only problem I see with my code is a null if there is a filesx or files0,1,3
@viviet I think this is the answer you need, by using Objects (as I suggested) you'll loose the index order of groups!
@mplungjan apologies, I totally missed in OP'squestion the "order by index" thing. +1
|
1

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) );

8 Comments

This code is first reducing and then taking Object values to get rid of the key of the byFieldName - that is not efficient - it is safer than relying on the digit on the key, but if that is guaranteed, then my code is more efficient
This will order the final array by the order in which fieldname values are encountered in the input array. You will need to sort the original array by fieldname before reducing using this approach.
Object or Array - that's data. You @mplungjan can ignore the second console log and treat this answer as if the first is uncommented. You'll loop data anyways if you need to retrieve the values. The better part in having it as structured Object is that you can take - if necessary - directly the entire array by using it's key: const fn1 = byFieldName["files0"] when using an array you need to access the deep layers and iterate them as soom .some() of the items matches the desired key.
@pilchard Objects property order is predictable in JavaScript ES2015 - the loop thereafter has no difference in entry.
pilchard yes I know, but that's unnecessary for this suggestion (which is to just group them and enjoy the benefits - tough not alphabetically ordered) additional iterations could be too expensive for something @mplungjan already solved. - And PS, I missed in the question the OP's need to order by index.
|
1

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.