javascript - 循环遍历 JSON 以按键对值进行分组
问题描述
我有一个 JSON 文件,其中包含一堆歌曲以及相关的歌曲行、诗句编号等。我的目标是打印每个不同的诗句。我很难构建一个有效的循环。这是 JSON 文件的示例:
[{ "song": 1, "verse": 1, "lineNum": 1, "line": "Mato Joe Tsinki"},
{ "song": 1, "verse": 1, "lineNum": 2, "line": "Chiti chiti"},
{ "song": 1, "verse": 2, "lineNum": 1, "line": "Raro Raro"},
{ "song": 1, "verse": 2, "lineNum": 2, "line": "Shinan Kibi"},
{ "song": 1, "verse": 2, "lineNum": 3, "line": "Bewa bewa"},
{ "song": 2, "verse": 1, "lineNum": 1, "line": "Ramo Kano"},
{ "song": 2, "verse": 2, "lineNum": 1, "line": "Choro Choro"},
{ "song": 3, "verse": 1, "lineNum": 1, "line": "Pisha Pisha"}]
在这个 JSON 中,总共有 5 节经文。
- 歌曲 1,第 1 节:“Mato Joe Tsinki”/“Chiti Chiti”
- 歌曲 1,诗歌 2:“Raro Raro”/“Shinan Kibi”/“Bewa Bewa”
- 歌曲 2,第 1 节:“Ramo Kano”
- 歌曲 2,第 2 节:“Choro Choro”
- 歌曲 3,第 1 节:“皮沙皮沙”
我写了以下内容,成功打印了每首歌的第一节,但没有打印后续的诗句。
var fs = require('fs');
var colors = require('colors');
fs.readFile('stackoverflow.json', 'utf8', function (err,data) {
data = JSON.parse(data);
for(var i in data) {
var item = data[i];
// construct string song:verse:line
var lineIndex = item.song
lineIndex += ":"+item.verse
lineIndex += ":"+item.lineNum
var numSongs = 20
var songNum = 1
var verseNum = 1
var lineNum = 1
// console.log(verseNum)
while(item.song <= numSongs && item.verse == verseNum)
{
console.log(lineIndex.green + ' ' + item.line);
verseNum++;
}
}
});
更新以演示所需的输出控制台日志:
歌曲 1 第 1 节:“马托·乔·辛基”“Chiti Chiti”
歌曲 1 节 2:“Raro Raro”“Shinan Kibi”“Bewa Bewa”
歌曲 2 节 1: ....
解决方案
您可以使用reduce
对经文进行分组并使用和的每个唯一组合创建一个累加器对象,song
因为verse
它是key
s。并且,然后用于Object.values
获得最终输出。这将为和lines
的每个组合创建一个数组:song
verse
var verses =
[{ "song": 1, "verse": 1, "lineNum": 1, "line": "Mato Joe Tsinki"},
{ "song": 1, "verse": 1, "lineNum": 2, "line": "Chiti chiti"},
{ "song": 1, "verse": 2, "lineNum": 1, "line": "Raro Raro"},
{ "song": 1, "verse": 2, "lineNum": 2, "line": "Shinan Kibi"},
{ "song": 1, "verse": 2, "lineNum": 3, "line": "Bewa bewa"},
{ "song": 2, "verse": 1, "lineNum": 1, "line": "Ramo Kano"},
{ "song": 2, "verse": 2, "lineNum": 1, "line": "Choro Choro"},
{ "song": 3, "verse": 1, "lineNum": 1, "line": "Pisha Pisha"}]
const merged = verses.reduce((acc, { song, verse, line }) => {
const key = `${song}-${verse}`
acc[key] = acc[key] || {song, verse, lines: []};
acc[key]["lines"].push(line);
return acc
}, {})
const output = Object.values(merged)
console.log(output)
如果您想lines
用 a 分隔/
,请使用字符串属性并连接每个line
:
var verses =
[{ "song": 1, "verse": 1, "lineNum": 1, "line": "Mato Joe Tsinki"},
{ "song": 1, "verse": 1, "lineNum": 2, "line": "Chiti chiti"},
{ "song": 1, "verse": 2, "lineNum": 1, "line": "Raro Raro"},
{ "song": 1, "verse": 2, "lineNum": 2, "line": "Shinan Kibi"},
{ "song": 1, "verse": 2, "lineNum": 3, "line": "Bewa bewa"},
{ "song": 2, "verse": 1, "lineNum": 1, "line": "Ramo Kano"},
{ "song": 2, "verse": 2, "lineNum": 1, "line": "Choro Choro"},
{ "song": 3, "verse": 1, "lineNum": 1, "line": "Pisha Pisha"}]
const merged = verses.reduce((acc, { song, verse, line }) => {
const key = `${song}-${verse}`;
if(acc[key])
acc[key]["lines"] += " / " + line;
else
acc[key] = {song, verse, lines: line};
return acc
}, {})
const output = Object.values(merged)
console.log(output)
推荐阅读
- python - 显示一维形状的二维 numpy ndarray
- python - psycopg2.DataError:整数的输入语法无效:“” WHERE Toys.toy_id = ' '
- scala - Scala - 用随机数填充 Seq,没有重复,并且始终具有相同的大小
- javascript - 使用 React 和 Ant Design 的浮动标签
- python - 如何将多级索引转换为 Python 中的列。(IndexError:不能从空轴中进行非空拍摄。)
- python - 通过输入获取半径的程序找到表面积和体积
- blockchain - 在面向客户端的应用程序中使用 web3 库是否安全?
- r - 将数据加载到 R 中的最佳文件类型(速度方面)?
- nginx - Rundeck 与 nginx 上的其他站点,其他站点是 php
- python - 激活后虚拟环境没有影响