我如何分离每个 JSON 对象并将它们分组到 JavaScript 中的数组?

Posted

技术标签:

【中文标题】我如何分离每个 JSON 对象并将它们分组到 JavaScript 中的数组?【英文标题】:How could I separate each JSON object and group them to an array in JavaScript? 【发布时间】:2021-03-13 09:01:15 【问题描述】:

multer.js 中的 req.files 示例

[
    
        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
      
]

我想用它们的字段名动态地对每个 JSON 对象进行分组,并将它们存储在一个对象数组中,同时使用它们的字段名编号作为它们的数组索引。

组可以介于 0 到 9 之间,具体取决于用户输入。

我希望的结果是这样的

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
        ,
    ]
    ...
    
]

如果存在,someArr[9] 会返回

[

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

我尝试的是首先从字段名中解析整数并将它们重新分配为它们的值,以便更好地使用 for 循环进行排序

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

但是从这里开始,我找不到将这个元素(thisFile)推送到哪里,因为我无法在上层范围内预先声明每个数组,因为它们也需要动态创建。

【问题讨论】:

请接受@mplungjan 的回答。我错过了您需要按索引排序01 等。使用对象非常适合分组,但最终顺序不会按键的字母顺序组织。 @Roko C. Buljan 检查!我一定也会记住您的解决方案! 【参考方案1】:

如果您不一定需要按索引排序 files[index]

在这种情况下,您可以将 Array.prototype.reduce() 转为 Object。 您的对象将按fieldname 属性分组不是按字母顺序排列),其中包含一个数组,其中项目具有相同的属性键。 使用Object.values()(如果需要,还可以使用Array.prototype.forEach())迭代您的对象。

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

【讨论】:

此代码首先减少然后取 Object 值以摆脱 byFieldName 的键 - 这不是有效的 - 它比依赖键上的数字更安全,但如果可以保证,那么我的代码效率更高 这将按照在输入数组中遇到字段名值的顺序对最终数组进行排序。在使用这种方法减少之前,您需要按字段名对原始数组进行排序。 对象或数组 - 那是数据。您@mplungjan 可以忽略第二个控制台日志并将此答案视为第一个未注释。如果您需要检索值,无论如何您都将循环数据。将其作为结构化对象的更好之处在于,如果需要,您可以使用它的键直接获取整个数组:const fn1 = byFieldName["files0"] 当使用数组时,您需要访问深层并将它们迭代为 soom .some()项目与所需的键匹配。 @pilchard Objects 的属性顺序在 javascript ES2015 中是可预测的——此后的循环在条目上没有区别。 pilchard 是的,我知道,但这对于这个建议是不必要的(即只是将它们分组并享受好处 - 很难不按字母顺序排列)额外的迭代可能太昂贵了@mplungjan 已经解决了一些问题。 - PS,我错过了OP需要按索引排序的问题。【参考方案2】:

我会使用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)

注意:组可以在 0 到 9 之间,具体取决于用户输入。

我假设没有漏洞,因为这可能导致数组稀疏

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

将创建一个数组

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

【讨论】:

干净简单!!很好的答案!我应该寻找减少 @mplungjan 是的,知道了!没有字段名replace -ing!耶! :P ;) 如果有 filesx 或 files0,1,3,我看到的唯一问题是我的代码为空 @viviet 我认为这是您需要的答案,通过使用对象(正如我建议的那样),您将失去组的索引顺序! @mplungjan 道歉,我在 OP 的问题中完全错过了 “按索引排序” 的事情。 +1【参考方案3】:

我尽量不修改你的逻辑来做到这一点。 如果没有files2,则filesArray[2] 将是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)

【讨论】:

以上是关于我如何分离每个 JSON 对象并将它们分组到 JavaScript 中的数组?的主要内容,如果未能解决你的问题,请参考以下文章

PromiseKit 6:如何创建多个并发 Promise 并将它们各自的结果分组到一个数组中?

如何对 JSON 项目进行排序/分组

如何在 C# 中迭代​​ JSON 并将每个对象添加到 List?

维护嵌套元素的分组方法 XSLT 2.0 - 分离多余的

如何从嵌套 Json 数组角度 2 打印和分离键和值并将其添加到选择框中

Python - 在字典列表中查找重复项并将它们分组