You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:JavaScript实现歌词和弦对应排版的代码问题

问题描述

需要编写一个JavaScript函数,接收包含方括号包裹和弦的歌词输入,统计和弦前方的字符数量,将和弦输出在对应歌词行的上方,并根据前置字符数设置正确的间距,生成和弦与歌词对齐的乐谱。

示例输入:

This is a [G]lyric to a [C]song
I could [D]sing it all day [Em]long

期望输出:

G           C
This is a lyric to a song
        D               Em
I could sing it all day long

现有代码仅输出和弦行且间距错误,无法实现需求:

function processText(input) {
  const lines = input.split("
");
  let output = "";

  for (let line of lines) {
    let startIndex = line.indexOf("[");
    let endIndex = line.indexOf("]", startIndex);

    let lastIndex = 0;
    let lineOutput = "";

    while (startIndex !== -1 && endIndex !== -1) {
      const padding = startIndex - lastIndex;
      const content = line.substring(startIndex + 1, endIndex);

      lineOutput += " ".repeat(padding);
      lineOutput += content + " ";

      lastIndex = endIndex + 1;

      line = line.substring(endIndex + 1);
      startIndex = line.indexOf("[");
      endIndex = line.indexOf("]", startIndex);
    }

    lineOutput += line.substring(lastIndex);
    output += lineOutput.trim() + "
";
  }

  return output;
}

const input = `This is a [G]lyric to a [C]song
  I could [D]sing it all day [Em]long`;

const output = processText(input);
console.log(output);

当前输出:

G  C
           D     Em
问题分析

现有代码存在以下核心问题:

  1. 仅生成和弦行,未保留去除和弦后的原歌词行,导致输出缺少关键内容。
  2. 循环中修改原line变量,后续startIndex基于截断后的字符串计算,与原字符串索引错位,导致间距计算错误。
  3. 未考虑和弦被移除后歌词行的长度变化,无法正确对齐和弦与对应歌词位置。
修正后的代码
function processText(input) {
  // 按行分割并过滤空行
  const lines = input.split('\n').filter(line => line.trim() !== '');
  let output = '';

  for (const originalLine of lines) {
    // 匹配所有[和弦]格式,获取内容与原位置
    const chordMatches = [...originalLine.matchAll(/\[([^\]]+)\]/g)];
    // 生成去除和弦的干净歌词行
    const lyricLine = originalLine.replace(/\[([^\]]+)\]/g, '');
    // 初始化和弦行:用空格填充至歌词行长度
    let chordLine = ' '.repeat(lyricLine.length);

    // 逐个处理每个和弦,计算对齐位置
    for (const match of chordMatches) {
      const chord = match[1];
      // 原字符串中[的起始索引
      const originalStartIndex = match.index;
      // 计算和弦在和弦行中的位置:减去前面所有[和弦]占用的3个字符长度
      const previousChordsCount = chordMatches.indexOf(match);
      const chordPosition = originalStartIndex - previousChordsCount * 3;

      // 将和弦替换到对应位置
      chordLine = chordLine.substring(0, chordPosition) + chord + chordLine.substring(chordPosition + chord.length);
    }

    // 若和弦行非空则添加,再添加歌词行
    if (chordLine.trim() !== '') {
      output += chordLine + '\n';
    }
    output += lyricLine + '\n';
  }

  return output.trim();
}

// 测试输入
const input = `This is a [G]lyric to a [C]song
I could [D]sing it all day [Em]long`;

const output = processText(input);
console.log(output);
代码解释
  1. 匹配和弦:使用matchAll正则匹配所有[和弦]格式的内容,同时获取每个和弦在原字符串中的起始索引,避免手动循环索引的错误。
  2. 生成歌词行:通过replace移除所有[和弦]内容,得到干净的歌词行。
  3. 初始化和弦行:用与歌词行等长的空格填充,保证和弦行与歌词行的长度一致,基础对齐。
  4. 计算和弦位置:每个和弦的对齐位置 = 原字符串中的起始索引 - 前面已处理和弦的数量×3(每个[和弦]占3个字符,移除后需修正位置)。
  5. 填充和弦:将和弦替换到和弦行的对应位置,实现精准对齐。
  6. 输出处理:过滤空行,避免多余内容;仅当和弦行非空时才添加,确保无和弦的行只输出歌词。

内容的提问来源于stack exchange,提问作者Aaron Phillips

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 15:05:09