javascript - 根据多个特定字符从平面字符串数组创建嵌套对象

标签 javascript arrays algorithm mapping reduce

我有一个大文本,使用正则表达式从中提取了标题字符串。标题以 1-6 个主题标签 (#) 开头。以下是输入数组的示例:

  const content = [
    "#1",
    "##1a",
    "###1a1",
    "###1a2",
    "##1b",
    "#2",
    "#3",
    "##3a",
    "##3b",
    "#4",
  ];
标题级别(字符串开头的主题标签数量)描述了某个标题在章节层次结构中的位置。我想将我的输入解析为一个标题对象数组,其中包含没有主题标签的标题文本和标题嵌套章节。上面数组的期望输出是:
export interface Heading {
  chapters: Heading[];
  text: string;
}

const headings: Heading[] = [
  {
    text: "1",
    chapters: [
      {
        text: "1a",
        chapters: [
          { text: "1a1", chapters: [] },
          { text: "1a2", chapters: [] },
        ],
      },
      { text: "1b", chapters: [] },
    ],
  },
  { text: "2", chapters: [] },
  {
    text: "3",
    chapters: [
      { text: "3a", chapters: [] },
      { text: "3b", chapters: [] },
    ],
  },
  { text: "4", chapters: [] },
];
我尝试编写一个解析字符串的函数,但陷入了如何知道当前字符串属于哪个标题输出的问题:
export const getHeadings = (content: string[]): Heading[] => {
  let headingLevel = 2;
  let headingIndex = 0;
  const allHeadings = content.reduce((acc, currentHeading) => {
    const hashTagsCount = countHastags(currentHeading);

    const sanitizedHeading = currentHeading.replace(/#/g, "").trim();
    const heading = {
      chapters: [],
      text: sanitizedHeading,
    };

    if (hashTagsCount === headingLevel) {
      headingIndex = headingIndex + 1;
    } else {
      headingIndex = 0;
    }

    headingLevel = hashTagsCount;
    if (hashTagsCount === 2) {
      acc.push(heading);
    } else if (hashTagsCount === 3) {
      if (acc.length === 0) {
        return acc;
      }
      if (acc.length === 1) {
        acc[acc.length - 1]["chapters"].push(heading);
      }
    } else if (acc.length === 2) {
      acc[acc.length - 1]["chapters"][headingIndex]["chapters"].push(heading);
    } else if (acc.length === 3) {
      acc[acc.length - 1]["chapters"][headingIndex]["chapters"][headingIndex][
        "chapters"
      ].push(heading);
    }
    return acc;
  }, []);
  return allHeadings;
};
虽然这适用于非常简单的情况,但它不可扩展并且具有预定义的标题级别(使用 if 语句)。我怎样才能以级别(主题标签)的数量无关紧要的方式重写它?

最佳答案

reduce 基于方法可以继续跟踪/管理正确的(嵌套)chapters需要将新章节项目插入的数组。
因此,累加器可以是一个对象,除了 result数组具有要跟踪的嵌套级别 chapters 的索引/映射数组。
将减少heading字符串被分解成它的 '#' (哈希)基于flag及其文字content部分。这是在以下正则表达式的帮助下完成的... /^(?<flag>#+)\s*(?<content>.*?)\s*$/ ... 特点 named capturing groups .哈希值 (flag.length) 表示当前嵌套级别。

function traceAndAggregateChapterHierarchy({ chaptersMap = {}, result }, heading) {
  const {
    flag = '',
    content = '',
  } = (/^(?<flag>#+)\s*(?<content>.*?)\s*$/)
    .exec(heading)
    ?.groups ?? {};

  const nestingLevel = flag.length;

  // ensure a valid `heading` format.
  if (nestingLevel >= 1) {

    let chapters;
    if (nestingLevel === 1) {

      // reset map.
      chaptersMap = {};
      // level-1 chapter items need to be pushed into `result`.
      chapters = result;
    } else {
      // create/access the deep nesting level specific `chapters` array.
     chapters = (chaptersMap[nestingLevel] ??= []);
    }
    // create a new chapter item.
    const chapterItem = {
      text: content || '$$ missing header content $$',
      chapters: [] ,
    };
    // create/reassign the next level's `chapters` array.
    chaptersMap[nestingLevel + 1] = chapterItem.chapters;

    // push new item into the correct `chapters` array.
    chapters.push(chapterItem);
  }
  return { chaptersMap, result };
}

const content = [
  "#  The quick brown (1) ",
  "## fox jumps (1a)",
  "###over (1a1)",
  "####  ",
  "###the (1a2)",
  "## lazy dog (1b)",
  "# Foo bar (2)",
  "# Baz biz (3)",
  "##buzz (3a)  ",
  "##booz (3b)  ",
  "# Lorem ipsum (4) ",
  "##",
];
const { result: headings } = content
  .reduce(traceAndAggregateChapterHierarchy, { result: [] });

console.log({ content, headings });
.as-console-wrapper { min-height: 100%!important; top: 0; }

关于javascript - 根据多个特定字符从平面字符串数组创建嵌套对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71716982/

相关文章:

c - 来自不兼容指针类型警告的初始化。找不到问题

algorithm - 1/x + 1/y = 1/N(阶乘)

javascript - 带有图像按钮的Onclick提交表单Javascript

javascript - HTML5中id的比较

javascript - 使用 JavaScript,将换行符插入 HTML textContent 属性(特定于 IE)

c - 读取单词的功能只读取每隔一个字母

c - 查找并打印带有空格或制表符分隔符的字符串的最后一个单词

java - 为什么我在 Hackerrank 上的这段代码中因超时而被终止?我的最后一次迭代没有发生?

python - 在列表中搜索一对整数的算法

javascript - 包装后合并文本节点并打开jquery