第0期 - 终末之时

373 阅读6分钟

开篇

在反复折腾了这么几年以后,回头看来2017年那时学习外加文章输出的时间是让自己感到最舒服的日子。最近在看了阮一峰(以下简称阮博)的周刊以后,觉得写作能让自己能从每天的看似平淡的日常中获取有所收获。虽然自己可能做不到持续输出,也许本次以后就遥遥无期,仅仅作为自己任性的行为。

技术方向

关于工程版本号

项目第版本号存在最佳实践第约定:语义化版本 / 语义化版本中文

概括来说,版本通常按照以下规范:

major.minor.patch-pre
例如:1.0.0-1

major: 主版本号,用于不兼容的API修改
minor: 次版本号,功能新增
patch: 修订号,问题修复
pre: 各种先行版,预览版,etc

通过语义化版本方式,版本版本本身具有可读性。平时业务开发过程中,没有思考过版本迭代规范(由于toB内部项目,也缺少了理应存在的changelog)。之前在微信小程序提交第时候,官方的版本号也是采用这种语义化的版本号定义规则,现在才了解到这大概是一种最佳实践。

前端项目可以考虑npm提供的命令行:npm version,来进行版本迭代。npm version也是遵照了语义化的规则,通过常用的参数,帮助我们更新package.json中的版本信息,并自动执行addcommit

npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease [--preid=<prerelease-id>] | from-git]

取消自动打tag功能,可以追加参数 --no-git-tag-version

详细内容可以参见:npm version

对于一个项目的,初始版本号通常是:0.1.0,当对外开放标注版本的时候可以使用1.0.0

算法

最近继续在弥补不足的算法知识,本周的几个排序算法都是基于分组的概念,算法复杂度理想情况下都是O(n)

1.桶排序

将大的数组对象,根据范围划分成多个小的数组(多个桶),桶内排序(使用快排)后合并。桶排序比较适合外部排序,例如:内存无法一次性加载所有数据的时候,将数据划分成不同的范围并用桶排序,最后再组合写出到文件,就能实现无法一次性全量排序的数据,这个解决大量数据的思路(分而治之),不过从排序规则来说,需要制定范围,所以可能更适合数字/或能转换为数字比较的数据排序(计算机世界其实都可以转换为数字,至少是二进制)。

以下例子中前提是数组元素均为自然数,如果需要包含负数或者非数字元素,则算法需要进行调整

function bucket_sort(arr) {
  // 将数据分成3个桶
  return bucket_sort_unit(arr, 3);
}
function bucket_sort_unit(arr, n) {
  // 找到桶内最大值
  let max = 0;
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] > max) {
      max = arr[i];
    }
  }
  // 单位桶的范围
  let unit = Math.ceil(max / n);
  let buckets = [];
  for(let i = 0; i < n; i++) {
    buckets.push([]);
  }
  
  // 将元素放到每一个桶中
 for(let i = 0; i < arr.length; i++) {
   buckets[Math.ceil(arr[i]/unit) - 1].push(arr[i]);
 }

 // 桶内自排序,并组合到一起
 let res = [];
 for(let i = 0; i < n; i++) {
   quick_sort(buckets[i]);
   res.push(...buckets[i]);
 }
 return res;
}
console.log(bucket_sort([1,3,20,9,5,6,10,83,29]));

2.计数排序

在桶排序的基础上,极端化到每个桶只有一个元素。根据王争老师的实现,最关键的点在巧妙利用数组元素值和其出现次数的关系,来构建所需要的数组。

function countSort(arr) {
  // 获取数组中元素最大值
  let max = 0;
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] > max) {
      max = arr[i];
    }
  }
  // 直接获取累加数组
  let plusBuckets = [];
  for (let i = 0; i < max + 1; i++) {
    plusBuckets[i] = 0;
  }
  for(let i = 0; i < arr.length; i++) {
    plusBuckets[arr[i]]++;
  }
  for (let i = 1; i < max + 1; i++) {
    plusBuckets[i] = plusBuckets[i - 1] + plusBuckets[i];
  }
  // 利用累加累加后数组的特性,计算数据
  let res = [];
  for (let i = 0; i < arr.length; i++) {
    // 获取到某个元素累加后到最大index
    // 这里的关键是要理解plusBuckets[arr[i]]代表什么
    // arr[i]是数组数据的值,相对于plusBuckets来说是其中的数组序号
    // plusBuckets是数组数据值出现次数得加后的结果
    let index = plusBuckets[arr[i]] - 1;
    // 最大到index就是某个元素应该到值
    res[index] = arr[i];
    // 元素占位以后,累加数需要-1
    plusBuckets[arr[i]]--;
  }
  // 为什么不用,因为解构本身应该可能用到循环,所以就变成了两层循环,计算复杂度就不一定是O(n)
  // let buckets = [];
  // for(let i = 0; i < max + 1; i++) {
  //   buckets[i] = [];
  // }
  // for(let i = 0; i < arr.length; i++) {
  //   buckets[arr[i]].push(arr[i]);
  // }
  // let res = [];
  // for(let i = 0; i < buckets.length ; i++) {
  //   res.push(...buckets[i]);
  // }
  return res;
}

因此总结规则其实就是:

1. 利用累加求和的方式获取到每个元素的最大序号
2. 通过原数组中元素出现次数和最大序号的关系,原数组中某个数出现一次,则将该元素填充在最大序号处
3. 最大序号-1后继续排序

3.基数排序

基数排序的分类思路是将一个数据(从思路上看对字符串排序似乎更合适),利用稳定排序算法,将的每一位分别排序,最后得到整体的排序结果。这里的前提是所有数据位数一致,如果不一致可以考虑使用0进行补位(字符串比较通常是通过ASCII码进行的比较)

Makefile

makefile的目的是配合make生成所需要的文件,且自带文件变化检测功能,标准格式:

<target> : <prerequisites> 
[tab]  <commands>

targetprerequisites最后其实都是落到文件上,因为make会对prerequisites文件进行比较,如果有变化才执行相关command过程,例如:

source: file1.txt file2.txt

file1.txt:
    echo file1 > file1.txt

file2.txt:
    echo file2 > file2.txt

所以command都会输出targetmakefile归根到底是为了创建一系列文件而生,这些创建的文件,可能会由其他的命令继续负责执行过程。

makefile的教程推荐阮博的(看了一些文章,阮博写的算是最简单明了的了):Make 命令教程GUN Make

一句话知识点

  1. React<Fragment> | <></>一定程度等同于Vue中的<template>,可以用作代码片段组合

  2. 无障碍a11y的能力可以用<label style="display:none">, aria-label, aria-labeledbody, title, alt等方式屏幕读取器可读

  3. HTML现在有哪些可以使用的Element:HTML Elements

  4. Chrome devtools中的lighthouse功能,可以简单分析出网站某页面的性能,并给出部分建议,例如B站首页: image.png

  5. Chrome87 devtools中开启实验的CSS overview功能,可以拉出全站的配色,字体,边框,背景色,依赖CSS加载,可以用作视觉参考

开启方式:devtools小齿轮 -> Experiment -> CSS Overview

非技术方向

《进击的巨人》完结

本周巨人完结,漫画自己没跟,不过基本上被剧透完了,个人对结局不置可否,因为后续篇章没有看,所以没有发言权,不过从目前来看,结局不太符合大部分人理想中的结局。每个人心中都有自己认为的一个标准,如果不能达到自己所预期的结果,这个作品就是失败么?多从各个角度看一下这个作品,可能这些不同的看法和原作本身一样值得品味:

知乎-如何评价进击巨人第139话(最终话)

知乎-漫画《进击的巨人》已经完结,如何评价这部作品?

比特币UTXO模型

两种交易模型:UTXO和账户交易模型

比特币使用UTXO交易模型,每次交易都会产生UTXO,可以类比的纸币交付,例如:

我有2块钱,我要买1块钱的零食,我需要给2块钱给商家,商家再找给我1块钱,而不是我直接支付宝/微信转账1块钱(账户扣款)给商家,存在一个找零的过程。

每张纸币就是一个UTXO,但是和纸币交易也有区别,毕竟纸币交易的UTXO对应的价值是一定的,但是每个UTXO对应比特币价值基本上是不同的。

知乎-一文读懂比特币的 UTXO 模型

UTXO 与账户余额模型

四月新番

新一季的新番又来了,但是因为近期过审的原因,似乎题材上可能卡控更加严格了,且看且珍惜,目前本周还没补番,从目前了解到的情况,大概率会追《伊甸星园》(真岛浩老师新作),别的应该还包括上一季度的蜘蛛子和《勇者斗恶龙达伊的大冒险了》。

最后一提,上周补掉的《Re0》,确实是特别不错的佳作,虽然我不懂运镜,但是在人物刻画上的运镜,我只能说《Re0》真的细节,算是近今年特别推荐且续集保持高水准的作品了。

其他

阮博写的未来世界幸存者,虽然谈不上帮自己解决了多大困惑,但是总归是给到了一种解题思路。

每周其实新的输入比想象到多很多,只是很多被自己忽略了,碎片化的学习是需要更多时间的整理,才能体现其价值。

以上就是本周内容,大部分内容均为个人再加工观点,可能存在部分漏洞,欢迎大家指正。