我如何分离每个 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 的回答。我错过了您需要按索引排序0
、1
等。使用对象非常适合分组,但最终顺序不会按键的字母顺序组织。
@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 并将它们各自的结果分组到一个数组中?
如何在 C# 中迭代 JSON 并将每个对象添加到 List?