作者归档:白宦成

关于白宦成

独立开发者, 自由职业者, 写作者

girl reading book

我已经很久没有去图书馆了

在看订阅的 Newsletter 的时候,看到这样一段话。突然想起来,我似乎很久很久没有正经的去图书馆了。偶尔在商场里看到书店还会进去看一看,专门去图书馆真的是很少再去了。

d2b5ca33bd970f64a6301fa75ae2eb22 3

回想小时候,我常泡在图书馆里,周末往往是从吃完午饭呆到吃晚饭,一看就是看好几个小时。图书馆比较远,我有些时候也会去别的大型公立书店读书(新亚书店),放学以后就从家里走去书店看书,看几个小时再回家。

而从上了初中以后,因为学业的压力,就不怎么去书店的看书了。再加上初中开始,我将不少的时间投放在计算机上,去书店就越来越少了。

上了大学,我重新回到了有闲的状态,但我也再没回到过图书馆了。更多的时候,我都是直接买实体书了。毕竟我看的书大多是计算机相关的,等图书馆采购不知道猴年马月了。再加上大学时做了不少外包项目,也赚了一些钱,有钱就自己买。在大学时, 我除了买实体书,还买了 Kindle ,并订阅了 Kindle Unlimited 的,毕竟一年百来块,图书却可以一直借,很划算。

有钱,让图书馆离我越来越远了。回想一下,小时候喜欢去图书馆,大概是因为那个时候没钱买书,所以不得不去图书馆“白嫖”了。

floating green leaf plant on person's hand

如何拥有一个稳定的个人评价体系

人这一生难免会遇到不靠谱的朋友、上级、前辈,他们会在各种方面对你进行 PUA 。而一个对抗 PUA 的很重要的手段,便是构建一个稳定的自我认知和自我评价体系。

我们现在生活当中,接受着外部大量的信息和评价。对于我们身边的绝大多数人来说,我们不可避免在的在过去被父母拿来和其他同龄人对比(别人家孩子),也会有不少人因此留下阴影。在被对比的过程中,难免就会产生不健康的逆反心理和错误的自我认知和自我评价。

在我看来,一个稳定的自我认知源自于以己为本的自我评价体系。以己为本不意味着你不需要参考外界的信息,但你的出发点应该是你自己,而不是别人。父母的对比往往就是以他人为本,指责孩子为什么不如他人,他人才是基准。而以己为本的评价体系,则是以自己为基准,看自己和他人有哪些差距,如何缩小甚至完全没有差距。

而关于具体的制定自我评价的体系,我的建议是:

  1. 先明确「我是谁」。
  2. 再明确「我想要达成的目标」,这个目标可以是一个人,但不能是你直接联系得到的人(最好是已经去世的人,因为对于他们的评价已经基本定型,不会出现现在的明星塌房的事情)。
  3. 再明确「我和目标中间的人的水平」,这个目标同样可以是一个人,类似的,应该是一个你无法直接联系到的人。
  4. 当你明确了自己想要的目标之后,你已经大致知道他在历史上的位置。

现在,要解决的问题是,如何找到自己在历史上的位置。

前面我们提到,制定的目标需要是一个摸不到的、最好是已经去世,已经盖棺定论的人。而我们的参考系相对就没有这么麻烦。我们可以选择身边我们认为最厉害的人作为参考,进行对比,并通过对比找到自己的不足,补全这些不足。当我们已经超越了当下我们所定义的参考系之后,就可以重新寻找新的参考基准,并校准自己的认知。

在确立参考坐标系后,再不断的通过参考人来校准,从而让我们获得一个相对稳定且明确增长的个人评价。这样的个人评价体系在面对日常生活过程中的 PUA ,可以简单从容的去面对:你的评价是否是有价值的?对于我达成我的终极目标是否有效?。就算对方想要 PUA 你,也会因为无法动摇你内心的自我评价,而无法对你产生危害。

祝你拥有一个稳定的个人评价体系。

white floral on white book page

周报你可以不给别人看,但要自己写

在 V2ex 上有两个对立的帖子,写周报的意义何在?我个人觉得要认真写日报、周报、开好站会~

我自己的观点是:

  • 周报、日报可以不给别人看,但你应该自己给自己写一个周报/日报。这是为了帮你自己更好的做总结和记录,在日后需要的时候,有可用的资料。

我其实能理解那些反馈日报/周报的人的想法,在一个社交的场景下,周报和日报很快会流于形式,变成同侪压力( Peer Pressure),大家自然厌恶这样的内容和形式。但大家讨厌的是这种压力和无意义的竞争,而不是讨厌日报、周报本身。如果我将压力和记录拆开,则可以更好的看待日报、周报这些东西。

我们的生活当中需要处理太多的事情,这些事情往往在当下被我们一件件的处理掉,然后被我们抛之脑后。但这些小事,对于我们来说同样也是珍贵的经历和回忆。当日后我们希望回溯的时候,没有当下的记录,是一个十分困难的事情。

这也是后来为什么我开始写日记,记录每天零零碎碎的琐事。哪怕我的日历里只有几张照片、 几个地名、零零散散的只言片语,也可以帮我在日后重新回溯历史,成为我宝贵的记录。

medical professionals working

从医生的“医学研”演化到工程师的“产学研“

最近在听「发热电台」,在最新的一期节目当中,提到了医生职业体系当中对于医生的要求:医学研一把抓。

  • :医生的本质工作,治病救人。一个好的医生应当是能够治病救人的。有治病救人的结果出来。
  • :医生的教学工作,带实习生。一个好的医生的成长周期是很长的,期间则得益于前辈们的提携,才能逐渐成长为一个优秀的医生。
  • :医生的研究工作,在医生的体系内, 论文是一个评职称非常重要的评估因素。一个好的医生需要有自己的研究成果。

上面这三点让医生们苦不堪言(毕竟我国医疗资源不足,医生们完成医的任务就已经精疲力竭了),纷纷吐槽。

但我从中却注意到,似乎我们常见的职业当中,很多并没有类似的要求。而实际上,医生的“医学研”的设定帮助医生延长了自己的职业生命周期。

将其迁移至软件工程师领域,则是产学研一把抓

  • :产是软件工程师的本质工作,负责完成工作中的任务,将想法变为现实。这也是大多数软件工程师的日常。
  • :学和医生的定义类似。好的工程师应该试着将自己掌握的知识教授给学生。这些学生可以是你身边的实习生,也可以是你在社交网络上的粉丝。重要的是将知识传承下去,以及通过教授验证自己是否真的学会了。
  • :研则和医生略有不同。一方面,你可以通过类似医生的方式,撰写论文, 提交自己的研究报告给各期刊,来完成自己的研究工作。另一方面,你的研究工作可以和你自己工作使用的各项基础依赖结合,以开源的方式来展示你的研究成功。

当然,我能想到,这样的三条达成是很难的。但就如同医生一样,当你能做好这三条的时候,大概率你的职业生涯也会被延长,不用担心所谓的 35 岁危机。

person playing poker

别只顾着低头拿牌

对于大部分普通的青年人而言,最大的问题不是不努力,而是没有努力的方向。

我们常看到青年们在学校中追逐着自己身边人的脚步,别人做什么,自己也做什么。他人拿到了什么样的奖项,我就一定要拿到什么样的奖项。

但从未思考过,到底什么是想要的?无限制的拿牌只会让你在焦虑当中深深的陷下去 —— 毕竟感觉自己拿到了更多的牌,应该就能赢了。

现实往往不是那么的简单,我们看到别人能赢,是因为他规划好了自己的路线,而我们没有按照自己的规划去拿牌,最后虽然手上牌多,但不能帮助自己很好的达成目标,一切都是白搭。

更好的方式是 —— 想明白自己想要的是什么,然后在想要的方向上努力去拿牌,然后达成自己的目标,成功和牌。

以终为始,很重要。

person reading book white sitting

线性内容与非线形内容:兼谈电子书与实体书

今天在在读网络空间的兴衰的时候,里面的一句话引起我的注意

人们在阅读文字时,常常快速扫描文字,找到感兴趣的部分再按照顺序细致阅读,这也达到了随机访问的效果。而音频与视频不能快速扫描,只能依然按照时间顺序快进或快退,来搜寻想要的内容,有较强的线性。

OrangeCLK

而我们所熟悉的音乐播放器的概念,也不过是更加方便的切换帧

现代音频视频播放器提供了进度条操作的接口,可以在时间轴上选取播放时间,有了一定随机读取的功能。但大体上音频与视频仍然是线性媒体,它只有按照时间顺序播放时才能提供意义,计算机提供的操作接口只是让人可以选择播放起点。音频视频中各帧内容只有时间关系,没有其他联系。

上面这段描述,突然让我意识到了我自己阅读习惯的一部分 —— 关于买书。

我算是一个比较喜欢买书的人,每年基本上都会买一些实体书和电子书来看,电子书我有4部 ,实体书有近 200 本。

我买的电子书和实体书也会有明确的方向倾向:

  • 工具书、计算机相关的,大多买实体书 、 PDF
  • 社科类图书、传记类图书,大多买 Kindle 电子书 / 微信

工具书买实体,是因为我在看工具书的时候会需要从目录快速导航到某个具体的细节,然后在这个细节里进一步快速跳转。在读这些工具书的时候,我的目标就是 —— 快速读完,然后解决问题,合上书。

除了工具书之外,我还会把一些我在电子书当中看到觉得不错,打算长期持续性阅读的传记等,买成实体书以便随时翻阅。

而社科类、传记类的图书,由于其内容和时间序、顺序阅读强相关,没有那么强的随意跳跃的诉求,携带方便的电子书就成了最佳的选择。

当时不明白自己为什么这么样选择,现在看看,大概是因为信息本身的特质决定的。

smartphone showing Google site

运用深度优先和广度优先算法获取更多的信息

我平时会看很多的文章,这些文章成为我不断的创作的重要的灵感来源和信息收集的来源,因此,我对于信息的收集和整理也颇为关注,只为收获更多的信息。

在实际的阅读当中,我会采用深度与广度优先结合的方式,来遍历我所看的文章、图书,从而获得一个更大范围要阅读的内容。

主题 · 深度优先遍历

我的阅读往往是从某一个主题开始的,通过搜索引擎,找到搜索引擎当中排行靠前的文章,作为我的主题文章。

d2b5ca33bd970f64a6301fa75ae2eb22 4
搜索获得主题文章

在阅读主题文章时,我会进行广度优先遍历,将文章当中提到的关联文章、参考链接用新标签页面打开放在后台,等待稍后处理完当前页面再进行阅读。这个时候,我阅读的文章就会从原本的一篇文章,变为 1 + 3 篇文章;

d2b5ca33bd970f64a6301fa75ae2eb22 5

在阅读完主题文章后,再依次阅读其相关文章 A、B、C。并在 A、B、C 的基础上,进一步挖掘相关文章 D、E、 F、G、H。此时,我阅读的文章变为了 1+3+5。

d2b5ca33bd970f64a6301fa75ae2eb22 6

现在,我要读的文章就从一开始的一篇主题文章变为了共计 8 篇文章,获取了 8 倍的信息。如果此时我的问题已经得到了解决,那么我就可以对这些信息进行收拢和汇总,达成我的目标。如果此时问题没有得到解决,则可以继续进行广度优先遍历,进行进一步的挖掘。

此外,如果到了某一层发现不再有相关的文章可以查看,则可以退回到搜索引擎,从第二篇开始重新进行主题级别的深度优先遍历。

作者 · 广度优先遍历

当我完成了当前主题的研究时,此时我仍然保有 8 篇文章的链接。窗口依然没有关闭,此时我会进行作者级别的广度优先遍历。

我会从当前的文章当中跳转到博客的归档页面或首页,从首页开始逐篇阅读下去,直到读完某篇博客。

d2b5ca33bd970f64a6301fa75ae2eb22 7

基于之前开的 8 个不同的页面,可以进一步广度优先各博客主的文章,并在感兴趣的文章当中进行进一步的深度优先遍历,来查看更多的内容。

长此以往,你会发现,自己要看的文章越来越多。当然,你也可以收集到越来越多的信息。

white printing paper with numbers

使用 Sheetjs 将 JSON Array 转化为 Excel

使用 node-excel-stream 来按行处理 Excel 数据 中,我提到,如果你希望简单的完成 Excel 的读取和处理,那么 node-excel-stream 是个不错的选择。而反过来,如果你希望将 JSON Array 导出为 Excel,那么 Sheetjs 是个不错的选择。

注意

Sheetjs 和 exceljs 不同,区分了商业版和社区版。我们这里使用的是社区版 Sheetjs CE

用法

使用 Sheetjs 对数据进行导出时,你只需要调用 XLSX 方法当中的 json_to_sheet ,就可以将你的 JSON Array 变为一个 worksheet,接下来只需要将其放入一个新的 workbook 当中,并导出为文件,就可以完成 JS 数据导出为 Excel。

const XLSX = require("xlsx");

const data = [
  {
    ...
  },
  ...
]

const worksheet = XLSX.utils.json_to_sheet(data);
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, "sheetNameIsFirst");
XLSX.writeFile(workbook, "output.xlsx");
Code language: JavaScript (javascript)
white printing paper with numbers

使用 node-excel-stream 来按行处理 Excel 数据

数据分析是一个非常常见的需求,而在实际的落地场景当中, Python 是使用最多的。不过我因为写了很久的前端,其实对于Python已经生疏了。当我开始启动项目时,就会选择执行 npm init 来初始化一个项目。既然如此,就试着使用 Node.js 来做数据分析。

在 Node.js 当中操作 Excel ,最好的便是 Exceljs。不过 ExcelJs 封装了大量的函数,对于绝大多数的数据分析场景来说,可能并不适用(也不一定,只是我比较喜欢用代码来描述逻辑,Excel 更多是一个导入导出)。

当明确了我只是需要一个简单的导入导出后,那么 node-excel-stream 就进入了我的视野。

读取 Excel 内容

和 Exceljs 不同,node-excel-stream 的封装相对简单,就是一个 Reader 和 Writer ,提供的方法也十分简单:读取文件、定义格式,按行处理内容;

需要注意的是,node-excel-stream 只支持 xlsx ,而不支持 xls,所以如果你用的是旧版,则需要重新保存成 xlsx 来进行处理。

let dataStream = fs.createReadStream('data.xlsx');
let reader = new ExcelReader(dataStream, {
    sheets: [{
        name: 'Users',
        rows: {
            headerRow: 1,
            allowedHeaders: [{
                name: 'User Name',
                key: 'userName'
            }, {
                name: 'Value',
                key: 'value',
                type: Number
            }]
        }
    }]
})
console.log('starting parse');
reader.eachRow((rowData, rowNum, sheetSchema) => {
    console.log(rowData);
})
.then(() => {
    console.log('done parsing');
});
Code language: JavaScript (javascript)

写入 Excel 内容

写入时和读取时相比,稍微复杂一点,需要将所有的输入使用 Promise.all包裹起来

let writer = new ExcelWriter({
    sheets: [{
        name: 'Test Sheet',
        key: 'tests',
        headers: [{
            name: 'Test Name',
            key: 'name'
        }, {
            name: 'Test Coverage',
            key: 'testValue',
            default: 0
        }]
    }]
});
let dataPromises = inputs.map((input) => {
    // 'tests' is the key of the sheet. That is used
    // to add data to only the Test Sheet
    writer.addData('tests', input);
});
Promise.all(dataPromises)
.then(() => {
    return writer.save();
})
.then((stream) => {
    stream.pipe(fs.createWriteStream('data.xlsx'));
});
Code language: JavaScript (javascript)

总结

如果你需要将 Excel 导入到 Js 当中进行处理,那么 node-excel-stream 是一个不错的选择。

black and yellow printed paper

warehouse — 一个简单易用的 JSON 数据库

在 Hexo 的 Github 组织下,有一个不明显,但却很有用的仓库 —— warehouse。

warehouse 是一个 JSON 数据库,基于 JSON 实现了各种类似于 SQL 的查询,可以帮助我们基于一个 JSON 文件来进行查询。在 Hexo 的静态生成过程中,warehouse 帮了大忙。

用官方的话来说,warehouse 就是 A JSON database with Models, Schemas, and a flexible querying interface.

在实际使用上,warehouse 确实如他所说的那边方便(虽然某些方法没有,但依然不影响他的使用很方便)。

Example

比如,如下代码就定义了 一个 Post 模型和对应的表。并实现了在这个表中插入一个新的数据。

var Database = require('warehouse');
var db = new Database();

var Post = db.model('posts', {
  title: String,
  created: {type: Date, default: Date.now}
});

Post.insert({
  title: 'Hello world'
}).then(function(post){
  console.log(post);
});
Code language: JavaScript (javascript)

如果你需要将这些数据保存为一个单独的文件,只需要修改初始化的参数,并执行 save 方法,就可以将 JSON 导出到指定的文件中

var db = new Database({
  path: "./test.json", // 将数据存储在 test.json 当中
});
db.save();
Code language: JavaScript (javascript)

类似的,如果数据已经构建好了,也只需要执行 load 方法,就可以加载数据。

var db = new Database({
  path: "./test.json", // 将数据存储在 test.json 当中
});
db.load();
Code language: JavaScript (javascript)

场景

如果你希望在内存当中对于 JSON 有一个更好的操作方式,那么 warehouse 是个不错的选择,不需要另外单独安装数据库,就可以实现类似于数据库的查询方式,体验还是非常好的。

如果你想了解更多,可以查看