【问题标题】:How to use reduce in a functional programming style to parse YAML front matter?如何在函数式编程风格中使用 reduce 来解析 YAML 前端?
【发布时间】:2017-06-06 04:50:04
【问题描述】:

我有一个文件想用 Javascript 解析:

---
title: This is a great title
date: 2012-03-02 11:30:00 -04:00
published: false
---

data_one
data_two
data_three

由此,我只想输出:

['data_one', 'data_two', 'data_three']

这意味着我需要跳过前五行。

虽然我可以轻松地让我的脚本自动跳过前五行,但我希望它足够健壮,即使在其中添加了额外的项目,它也会跳过前面的内容。这是我当前的实现:

const result = rawFileStr.split('\n')
  .reduce((acc, item) => {
    const endOfFrontMatter = acc === false && item === '---';
    const isFrontMatter = acc === false || item === '---';

    if (endOfFrontMatter) {
      return [];
    }

    return isFrontMatter ? false : acc.concat(item)
  }, [])

它基本上将累加器设置为false,表示它命中第一个---,然后在命中第二个---时,它返回一个空数组。

它有效,但所有这些 if 语句让我觉得这不是执行此操作的“功能方式”。有人可以阐明如何使用纯函数式编程来做到这一点吗?

【问题讨论】:

    标签: javascript arrays node.js functional-programming


    【解决方案1】:

    您可以使用正则表达式将行拆分,直到第一个 --- 不在第一行,然后得到其余部分:

    const result = rawFileStr.split(/^[^]*?\n---\n/).pop().split('\n');
    

    // Sample data
    const rawFileStr = `---
    title: This is a great title
    date: 2012-03-02 11:30:00 -04:00
    published: false
    ---
    data_one
    data_two
    ---
    data_three`;
    
    const result = rawFileStr.split(/^[^]*?\n---\n/).pop().split('\n');
    console.log(result);

    或者,如果没有正则表达式,您可以使用立即调用的函数表达式,它使用第一个 --- 出现的索引之后的项目(不在第一行)对数组进行切片:

    const result = (items => items.slice(items.indexOf('---',1)+1))(rawFileStr.split('\n'));
    

    // Sample data
    const rawFileStr = `---
    title: This is a great title
    date: 2012-03-02 11:30:00 -04:00
    published: false
    ---
    data_one
    data_two
    ---
    data_three`;
    
    const result = (items => items.slice(items.indexOf('---',1)+1))(rawFileStr.split('\n'));
    console.log(result);

    【讨论】:

    • 我对这个答案的唯一问题是,如果有人在文件中的任何位置(在前面的问题之后)放置一个带有额外 --- 的行,那么它实际上将无法读取所有内容。理想情况下,我只想跳到第二个---
    • 好的,我已经更新了我的答案,所以休息时间在第二个---
    【解决方案2】:

    您可以通过替换删除前面的内容,然后链接到拆分,然后使用过滤器确保不保留空字符串:

    let text = document.querySelector('textarea').value;
    
    let data = text
      .replace(/^---[\s\S]*?---/, '')
      .split(/\s+/)
      .filter(str => str.length);
    
    console.log(data);
    <textarea>
    ---
    title: This is a great title
    date: 2012-03-02 11:30:00 -04:00
    published: false
    ---
      
    data_one
    data_two
    data_three
    </textarea>

    【讨论】:

      猜你喜欢
      • 2022-11-30
      • 2012-07-30
      • 1970-01-01
      • 2016-03-18
      • 1970-01-01
      • 1970-01-01
      • 2016-05-01
      • 2010-11-08
      • 2016-07-25
      相关资源
      最近更新 更多