首页 > 解决方案 > 循环遍历 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,第 1 节:“Mato Joe Tsinki”/“Chiti Chiti”
  2. 歌曲 1,诗歌 2:“Raro Raro”/“Shinan Kibi”/“Bewa Bewa”
  3. 歌曲 2,第 1 节:“Ramo Kano”
  4. 歌曲 2,第 2 节:“Choro Choro”
  5. 歌曲 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: ....

标签: javascript

解决方案


您可以使用reduce对经文进行分组并使用和的每个唯一组合创建一个累加器对象,song因为verse它是keys。并且,然后用于Object.values获得最终输出。这将为和lines的每个组合创建一个数组:songverse

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)


推荐阅读