继续创作,加快成长!这是我参与「日新计划 10 月更文应战」的第2天,点击检查活动概况

前面现已初始化了项目,一起完结了ES Modules的装备。接下来咱们开端正式进入代码层面的学习。

语料库

首要在article目录下树立 resources 目录 ,在resources下树立一个data.json的json文件。咱们这个demo的中心便是经过随机取一些语料库的文字来组成一篇文章。

data.json如下:

{
  "title": [
  
  ],
  "famous":[
   "爱迪生{{said}},天才是百分之一的勤奋加百分之九十九的汗水。{{conclude}}",
   "查尔斯史{{said}},一个人简直能够在任何他怀有无限热忱的工作上成功。{{conclude}}",
   "培根说过,深窥自己的心,然后发觉一切的奇观在你自己。{{conclude}}"
  ],
  "bosh_before": [
   "既然如此,",
   "那么,",
   "我以为,"
  ],
  "bosh":[
   "{{title}}的产生,究竟需求如何做到,不{{title}}的产生,又会如何产生。 ",
   "而这些并不是彻底重要,愈加重要的问题是,",
   "{{title}},究竟应该如何完结。 "
  ],
  "conclude":[
   "这不禁令我深思。 ",
   "带着这句话,咱们还要愈加稳重的审视这个问题: ",
   "这启发了我。"
  ],
  "said":[
   "曾经说过",
   "在不经意间这样说过",
   "说过一句闻名的话"
  ]
 }

接下来开端测验编写JavaScript代码

随机模块(初版)

在项目根目录下创立一个lib目录,然后在lib目录下创立一个random.js的js文件,用于随机选取。

首要咱们需求编写一个函数用于随机数的选取。

function randomInt(min,max) {
    const p = Math.random();
    return Math.floor(min * (1 - p) + max * p);
}

上述函数能够获取min 到 max间的随机整数。

接下来咱们再写一个随机选取句子的函数,当fs模块读取完data.json后,将dataStr数组传给这个函数,就能够经过回来数组元素的内容完结句子的读取。(当然这个随机模块也有一点点小问题,我参阅了大佬的代码之后做了一些优化与处理,后面再说)

接下来咱们做个测验,先导入fs模块然后测验经过fs.readFile()进行data.json的读取,因为读取出来的数据是JSON,所以咱们还需求经过JSON.parse()来进行解析。该部分的悉数代码如下:

import fs from 'fs';
fs.readFile('../resources/data.json',{encoding:"utf-8"},(err,dataStr)=>{
    if (err) {
        console.log(err);
    }
    else {
        const array = JSON.parse(dataStr);
        console.log(array);
    }
})

咱们打印出的array发现是个数组,接下来咱们传入之前的randomPick()函数中


import fs from 'fs';
\
function randomInt(min,max) {
  const p = Math.random();
  return Math.floor(min * (1 - p) + max * p);
}
\
function randomPick(arr) {
  const index = randomInt(0,arr.length);
  return arr[index];
}
\
fs.readFile('../resources/data.json',{encoding:"utf-8"},(err,dataStr)=>{
  if (err) {
    console.log(err);
  }
  else {
    const array = JSON.parse(dataStr);
    console.log(randomPick(array.famous));
  }
})

咱们发现能够随机打印出一些话,比方如下

查尔斯史{{said}},一个人简直能够在任何他怀有无限热忱的工作上成功。{{conclude}}

爱迪生{{said}},天才是百分之一的勤奋加百分之九十九的汗水。{{conclude}}

…….

大概如上

模块化

作为一名开发者,咱们要考虑到许多因素,比方代码的整齐性,规范性,还要测验对咱们写的一些代码进行模块化,便于复用。

咱们将random.js中的代码进行模块化并导出(因为fs读取并调用randomPick()函数是用于给读者演示的,所以这儿删掉这些),代码如下:

export function randomInt(min,max) {
    const p = Math.random();
    return Math.floor(min * (1 - p) + max * p);
}
export function randomPick(arr) {
    const index = randomInt(0,arr.length);
    return arr[index];
}

接下来咱们假如要在其他地方引用这两个函数只需求import导入即可。

缺乏及解决

问题一

在随机选取的时候,可能会多次选取到同一条句子,虽然是狗屁不通文章生成器,但是连着好几句话如出一辙仍是很古怪,所以咱们应该不能彻底随机,假如重复选到相同的句子应该进行从头挑选。

咱们设置一个previous变量和一个now变量来记录两次结果。然后经过do…while来比对,再回来。

问题二

问题一的解决方案并不好,增加了选取的次数。参阅月影老师的文章,这儿咱们提出终究的解决方案

咱们这儿挑选用过程抽象的方法把它改成一个高阶函数

export function randomInt(min,max) {
    const p = Math.random();
    return Math.floor(min * (1 - p) + max * p);
}
export function randomFun(arr) {
    areReal = [...arr];
    function randomPick() {
        const right = areReal.length -  1;
        const index = randomInt(0,right);
        const pick = areReal[index];
        [areReal[index],areReal[right]] = [areReal[right],areReal[right]];
        return pick;
    }
    randomPick();
    return randomPick;
}

终究版别如上,代码略微有一些复杂。randomInt()的功能上面现已手把手写过了,这儿就不多赘述了。

高阶函数randomFun()中,首要copy了数组副本areReal,接下来对数组的操作都是针对副本数组的,不会改变原数组。然后又写了一个randomPick()函数,从第一位到最终一位的前一位进行随机抽取,抽取完的放到最终一位,这样就能够防止两次选到同一条句子。函数写完后,先调用一次,这样首次结尾元素便是随机的,充分保证了随机性。

基于node.js开发的文章生成器(二、语料库的读取与生成句子)就告一段落了,咱们有了上述函数就能够随机抽取句子了。第三部分明日继续。