旅行游记

去了大连。

感觉也是个很有意思的城市,长江路、天津街……这样的命名方式在青岛的时候也遇到过呢,作为2023年的行程,目前去过了大连、青岛、宁波。终于可以活动活动,感受中国的大好河山。

爱丽丝的屋顶,在一个商场中偶然看到的布景,可惜了,可惜了,如果在北京一定一堆人打卡

来到了十一假期,终于有空闲的时间可以思考了。想把博客的内容再更新一下,至少把旧博客都迁移过来,结果第一件事就是又又又更新了主题。这次更新希望能稳定一段时间。
看看博客时间,高质量的输出依然很少,虽然最近做了不少东西,但是能静下心来写的依然很少。

FTP文件扫描脚本

背景情况

公司有个FTP,里面是一些共享文件:研发、行政等等都会往里面放东西。作为一个共享文件服务它足够简单,作为一个内网应用,也足够好用。用了很久了之后,现在要做一些改进,所以,希望知道目前一共有多少文件,这样也可以估算一下未来准备多少硬件。从安全角度考虑,我还没有拿到这个FTP系统的访问权限(拿到了我也不想贸然登录服务器,服务一切正常的时候尽量不要乱动)。统计文件的工作项目在我的“待办列表”里待了很久很久,终于在一个阳光明媚的上午,我准备把它处理好。

过程故事

开始我把这个问题想简单了,我美滋滋的把这个任务丢给opencat(powered by gpt),结果,因为没有任何上下文的情况下,她给我回了一个shell脚本,用bash直接驱动lftp命令。

猫猫不开心

我隐约感觉不太对,直接的第一反应就是python。然后就开始了折腾,中间故事不表了,只说结果:我进坑了。ftplib是默认的库,运行效率特别低会卡死,考虑到有大量文件,默认的库可能确实性能不太好也可以理解(并不能……),我尝试更换了ftputil,结果中文支持不好。

最终回到了了bash+lftp的组合,值得庆幸的是,我很喜欢这个组合。并且也知道了,不要随便用python,ftp是那个年代的东西,就应该搭配同年代的工具

幕间休息

中午吃了一些好吃的😋

抓取数据

和之前抓取数据不同,这次我并没有记录抓取进度,而是根据根目录下的文件夹,一个个抓取的。想起了上次抓取数据的经验,抓取过程肯定会断掉:所以断点重连和进度保存看似麻烦却实际上是必要的。这次让我惊喜的是,lftp自己有断点重连功能!!现在回头看看,不能太喜新厌旧。
当然也有一些坑:比如文件名中可能有“空格”,这个被我考虑到了,但是问题出在存在“双空格”的情况,然后ls输出本来是多空格过滤为单空格:也就不能用awk了。改用用sed,然后发现macos的sed并不标准,准确的说,sed支持的正则表达式就不标准。文件名中的“&”这些就更不用说了。再比如,日期字段并不规范,如果是去年及以前的文件,就会用年月日,而当年的文件就会显示具体时间。好在,这些小的细节gpt就可以帮忙了。

结果

我拿到了所有的数据列表,截止6月5号的文件快照有了一份~可以作为后来分析扩容的基础了。更加开心的事情是,我的待办列表可以清除一项了。

最终代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# this script (maybe) only working on mac
# FTP server credentials
FTP_USERNAME="username"
FTP_PASSWORD="password"
FTP_SERVER="257.257.257.257"

#change this ^_^
now="/firstdir"
OUTPUT="./output/now.txt"

#the function
function getFiles() {
local path="$1"
if [[ ${path: -1} != "/" ]]; then
path="${path}/"
fi
local scriptpath=$(echo "$path" | sed 's/ /\\ /g' | sed 's/&/\\&/g')
local output=$OUTPUT
local remote_files
local size line
local filename
local first
lftp -u "$FTP_USERNAME","$FTP_PASSWORD" "$FTP_SERVER" <<EOF
cd $scriptpath
ls > /tmp/files.txt # list all files and directories and save to a temporary file
bye
EOF
while read line; do
filename=$(echo "$line" | sed -n -r 's/^.*[Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec]{3} [0-9]{2}[[:space:]]+([0-9]{4}|[0-9]{2}:[0-9]{2}) (.*)$/\2/p')
echo $line >> "${output}"
first=${line:0:1}
if [[ $first == 'd' ]] ; then
echo "$path$filename"
getFiles "$path$filename"
fi
done < /tmp/files.txt
}
getFiles "$now"

小结

这个代码写完花了整整4个小时,一个上午的时间都在写,写的过程中想着还有其他的事情要处理。总之,并不是个很开心的工作,原因是心态问题,我一开始忘记了这个工作中肯定会出现各种“细节”需要不断调试,如果一开始就知道的话,心态能好很多。开心面对自己喜欢的工作应该是非常幸福的事情。

建立一个全球可用的高速文件共享方案:开始就是曲折探索路径

背景情况

跨区域的团队协作存在的很多问题,想象一下,团队成员在伦敦、硅谷、西安、北京,团队中领域专家、有数据科学家等,提供IT工具协调大家共同开展一个项目存在很多挑战。我目前碰到的一个问题是,如何在这些团队成员间共享文件,核心需求是”快”,并且足够“简单”。作为简单来说,第一个能想到的就是FTP服务了,虽然古老,但是这个协议确实足够简单,然后就开始了我的折腾之旅。

FTP代理方案

先考虑一个简单的情形,英国有个团队,北京有个团队,FTP服务器设置在北京团队的工作地点。这个情况下,北京的团队访问ftp速度是非常快的(8-10M/s),此时英国团队的访问速度就很慢了。当前阶段,现有团队喜欢了FileZilla做客户端下载文件。如何使得现有的使用习惯维持尽可能的不变提高速度呢?我想到了第一个方案就是FTP代理方案了。

FTP的代理不太多。第一个默认想到的就是反向代理方案,“对他使用Nginx吧”。但其代理缺点非常明显,就是配置特别复杂,因为FTP的passive模式,需要开放大量端口,这样公开报漏的服务器也不会安全[^1]。另外一个是使用专用的FTP代理软件,各种找只找到一个ftp.proxy[^2]。看了一下,12年没有更新了。当然,我还是花时间试了一下,结果失败了(纪念我的一个小时时间),并不是个很好使用的方案。

不自觉的就想到了这张图

12年前的更新,这也太久了

当然最重要的一点是,这样真的能提速吗?原来的模式是,英国团队直接访问北京的服务器,如果添加一个代理,比如代理放到香港,那么带宽如何处理?英国到香港再转到北京真的能速度快吗?这个时候我又思考了一下初衷,可能团队需要的就是一个“快”而“简”的文件共享服务。如果精力放到代理上是不是错过了关注点?

一个新的独立的中间服务器

建立一个中间FTP服务,地理位置上位于英国和中国中间,这样让两边都可以有适当的访问距离。这个时候我想到了点子是:掉换主服务器和备份服务器的位置。本来我的计划里,要用腾讯对象存储(COS)来备份所有的文件的,要不把方向调转过来,使用COS作为主服务器,然后利用本地每日进行备份,这样所有的团队都可以访问中间服务器,也许速度能平衡一下?说干就干~

比较可惜,COS默认是不支持FTP服务的,官方提供了COSFTPserver工具[^3]。这里要吐槽一下腾讯云提供的这个工具,虽然不是不能用,实际配置过程中也确实有必要的提示,不过,使用腾讯自己的虚拟机依然配置困难(我碰到的问题是python依赖安装出问题,最终通过virtualenv模块顺利解决)。实际配置好之后,使用起来并不稳定,首先是挑选客户端,我常用的FE file explorer pro直接挂掉,以至于我一只以为没有配置好,最后发现FileZilla、cyberduck到是可以正常使用。缺点也是特别明显,就是速度慢,一些基本操作支持的并不好,比如,list速度比正常FTP慢很多,再比如,文件夹移动并不支持(勉强可以移动文件)。实现原理所限,估计也无法配置用户权限了。最后,也是最大的问题,速度的瓶颈在虚拟机器的带宽上。我之前没有想明白,就算用对象存储,实际流量也是先经过了架设FTP服务的虚拟机。比如,我使用轻量应用服务器的情况下,服务器只有1M带宽,然后此时的下载速度就只有可怜的200k/s。如果使用按量付费的服务器,带宽可以设置很高,此时北京的上传下载速度可以有1-2M/s,不过流量太贵了,1rmb/G,并且,如果按月选择高带宽的机器,价格更是贵的离谱,另外,可能还需要支付COS的费用。

这个速度是肯定不行的,太水了,头疼

速度虽然快了,不过价格也高了,服务稳定还好,但是不稳定啊,而且贵!

看看这配置费用,仅仅是配置,就敢要这个价格,这些云厂商都该玩球

最终这个方案暂时放弃了,价格贵,且很难保证稳定。我继续又想了,两个方案如果都不太行,是不是可以暂时放弃FTP的方案,关注于“高速文件共享”。

尝试围绕cloudFlare看看有没有合适的解决方案

重新会到起点,我现在实际需要的是一个Building a Global High-Speed File Sharing System,这就让我想起了cloudflare,他的R2支持多地区部署,如果直接用R2是不是可以解决速度问题,并且,他的下载流量是不收费的,配合合适的工具[^4],本地备份可以没有费用。cf试图解决的问题就是全球化部署应用,这种功能聚焦让我稍稍有点兴奋——爷我也要部署一个全球应用了。先找一些简单的项目试试,很可惜,cf的R2太新了,没有成型的适配项目(如果我有时间精力一定自己做一个……唉),我随手找到了flaredrive[^5]稍稍做尝试就配置成功了,作者自己也提供了在线试用[^6]。一开始我非常兴奋,但是稍加冷静发现了问题,过于简单了。比如,不支持重命名,不支持文件移动。我上传大文件的时候,没有任何进度提示,对用户过于不友好从而使这个项目不可用了。类似的我还找到了R2-Explorer[^7],这次有了经验,看到TODO列表就知道不能用了,太简单了,甚至不能重命名文件夹。

不能重命名文件夹……cloudflare的各类项目还是新了,成熟的项目不多,需要时间、很多很多时间

简单的cf应用貌似走不通了,调研中我看到一个非常让我心动的商业软件R2FTP[^8],如果把R2变成FTP会怎么样呢?是不是直接解决问题,可惜,这个网站貌似是个PPT产品,只有一个首页,github链接是空的,twitter上也没有人。不过,R2FTP到是给了我一个新的思路。还是围绕R2,能否有包装的比价好的外围工具呢?还真有!!sftpcloud[^9]貌似就是这样的工具,他提供服务端,然后数据存在R2里。尝试了,依然失败(哈哈,我都平静了,这是个围绕失败的故事)。问题原因不明,不过,大概成功了也不一定会有好的效果,因为毕竟数据中转还是在ftp服务所在的节点,当然也许还有继续尝试的价值,不过,这个方案只能暂时封存了。

是的,我在失败中学到很多,不断的变换思路

幕间故事
对于加速产品,也调研了一些商用产品,比如Ftrans[^10]、raysync[^11],也尝试咨询了一下,不过这些方案都太有针对性了,基本都是关注于特定的领域(比如文件审核)。特别联系了一下ftrans的技术销售,具体实现方案需要在每个节点架设非常高性能的服务器,软件的授权价格也不是很美丽。

最终还是回到网盘方案

对FTP方案进行了诸多尝试之后,最终,还是回到网盘方案,继续看看nextcloud吧。借助nextcloud我又重新熟悉了一下docker操作。其中部署也不是那么顺利,特别是我用的都是便宜虚拟机,部署还特别慢(我甚至在一台古老的台式机上部署了一个nextcloud)。部署过程中我发现了新的问题,nextcloud太重了,操作繁琐,真的是团队需要的工具吗?直观来看我的待办列表里一直有一项,“给nc配置s3后端”,总是无法完成。我就重新思考,nextcloud真的是我需要的吗?

冷静下来,回到最开始的出发点,一个简单高速的文件分享服务。如果确定要用网盘实现,那么是不是还有其他的方案可以选择?于是,我不停的用关键词搜索其他的项目,然后得到了一串列表:seafile[^12],kodbox[^13],pydio[^14],filerun[^15]。seafile的简洁实用页面让我非常惊艳,真的是关注文件本身,而不是乱七八糟的其他东西(说的就是你,nextcloud)。kodbox可以找到serverless的部署教程,这也非常让我在意。在这个过程中,我不断的思考,“全球高速”,以至于要半夜从床上爬起来看CAP原理,想从最基础的角度考虑到我的解决方案,这是之前看过的一个重要博客出现在我脑海里————使用cloudflare部署全球高可用网站的方案[^16]。根据博客的思路,我完全可以把主机部署在就近的位置,用cloudflare的服务来就进回源,由于R2服务是最终一致的(也就是保证AP的),多节点主机也许也能获得不错的速度(至少保证能完成工作)。带着这个想法去看seafile的部署文件,发现了其中的问题:官方解答多节点部署必须相同域名,这个还不是主要问题,主要问题是官方的部署文件里使用memcache做小文件加速,必须每个节点同步,并且,官方不太保证这种部署方式,另外, 后端三个存储桶的保存要求,也让我意识到,目前这些网盘工具,关注点其实并不只是存储,重点在于meta信息(用户账户、文件评论、管理权限等)。

还是应该多游泳运动,我的好点子和灵感好多好多都是运动的时候想到的

小节

写了这么多,问题其实并没有被解决,不过,“我到底想要什么”这个问题在不断的失败、重新起步探索中被不停的聚焦了。比如,我越来越清楚,我需要的是个小而轻的工具。在多次部署cosftp的过程中,由于是用了COS存储,每次重新部署服务后,我之前的数据会突然出现在眼前,这让我意识到,我需要的是工具最好是和存储高度解耦的。一周的时间,每天1到数个小时,真的是让我重新找回了学习的感觉。

写下这段文字希望对后来人又帮助。


[^1]: 博客 Nginx反向代理FTP教程
[^2]: 官网 ftp.proxy - FTP Proxy Server
[^3]: 腾讯云文档中心 FTP Server 工具
[^4]: 对象存储备份工具rclone Rclone syncs your files to cloud storage
[^5]: flaredrive项目主页 github-flaredrive
[^6]: flaredrive demo flaredrive demo试用
[^7]: R2-Explorer项目主页 R2-Explorer
[^8]: R2FTP主页 FTP Servers for Cloudflare R2 Storage
[^9]: sftpcloud FTP & SFTPas a service.
[^10]: 飞驰云联高速ftp方案 Ftrans飞驰云联-飞驰传输
[^11]: 镭速传输方案 镭速传输-专为企业提供大数据加速传输方案
[^12]: seafile官网 Seafile开源的企业云盘
[^13]: kodbox官网 kodcloud可道云
[^14]: pydio官网 Pydio | Enterprise File Sharing & Sync Platform
[^15]: filerun官网 FileRun - Selfhosted File Sync and Share
[^16]: 博客 分布式部署 cloudflared 让访客就近回源

阅读与js相关的书籍

更新尽量不要停

如果没有什么内容,我更新一下读书笔记吧,就是这两本。

两本书,内容的部份有些过时了,不过思想还是非常值得学习

js的可靠代码,最终内容还是设计模式。这样也是非常有道理的,可靠就是解除耦合,解除耦合就是合理的设计模式,这本书自然而然的讲了如何用js实现各种设计模式。让我惊艳的地方有两点:

  1. 全书围绕着一个例子展开讲,把一个大会支持网站的例子的每一个部分都渐进式的讲到了;
  2. 全书都在坚持采用“测试驱动开发”的模式,讲解了如何测试各类设计模式;

内容方面,丰富的设计模式,让我反思之前没有好好学习应用设计模式是不是一种小损失。另一本,全家桶就看的比较快速了,毕竟更新的内容太多了。官方甚至都在主教程里推荐next.js了,肯定很多内容不相符。不过,我还是认真阅读了redux相关的内容,尝试去理解这个库的设计与使用。

其他随笔

把旧blog迁移过来的事情还没有进度,放松的的时候一篇一篇来吧。

打扫房间与第零篇文章以及开心

游戏还是很好玩的,不过要节制

经过了几天的思考,其实是拖延,终于决定写下这篇文章了。 metroid prime 通关了,可惜没有第一时间写在当时在游戏中进入冰雪世界的感受,估计再也不会写了。好消息是,至少留下了这份记录。prime最后的boss战挺失望的,不是我想象的那种感觉。让鸟人族搞的仪式感那么强的大灾害只是一个大鱿鱼似的东西,真的是莫名其妙。而且,打完了也不会怎么样……我更喜欢超级银河战士的结局,生存恐惧的结局也很棒。对了,我看完了超银的全收集视频,这个游戏太超前了,在sfc时代营造出如此恐怖与寂静的感觉,好多细节。比如,再次和metroid宝宝相遇的那个场景,好多灰色的敌人一碰就碎,然后小蜜宝宝出现,把怪物吸收成粉末……再然后,只有一滴血的情况下,小蜜宝宝离开……如果当初我能在合适的时间相遇这部游戏该多好呢?不过,我已经和月下相遇了,在最合适的时间,真的也不能奢求太多。

读书比较顺利,运动与读书,继续加油

最近恢复了运动与读书,看了spa相关的书籍。spa的开发也许更多是在实践中会有进步,如果只是理论,感觉不是太多。我看了测试驱动开发的书籍,有种恍然大悟的感觉。想起来接近10年前,我在学习mvc的时候,尝试所谓的测试驱动,可是失败了……那会儿如果我好好看看书,好好使用github也许我会更有收获也说不定。和老朋友交流的时候发现,我记了10年笔记,笔记软件各种更换,发现我没有利用起来这些记录……完全没有帮助,我没有再去看过,甚至自己也不想看。那么这些记录谁会看呢?我在这些记录上浪费的时间呢?当然有个好消息,我发现,我可以去看我曾经写下的博客,博客14年使用时间,最终文章寥寥可数,但是当我浏览的时候,确实找回了一些回忆,比如我学习symfony的记录。所以,我再次决定,从这篇开始换一个新的标题规则,所有文章用编号开始(这是为了便于后续文章的统计和管理),这边文章就是零了。
我在google的博客,确实也挺好用,但是不能有自己的域名和控制能力不足让我准备就停止在这一刻了

另外,我更换了新的域名,从长期的纠结中,我准备解放自己了。新的网址是https://oldyang.site,我发现我挺喜欢这个域名和名字的。这样就挺好。

最后,我要花一点点时间,至少把https://yangfs.blogspot.com上已经发表的文章迁移过来,作为一个新开始的纪念。可惜了那些最后没有发表的文章。

新的开始

我和自己和解了,开始自由的做自己喜欢的和有价值的事情,用知识地图去规划未来的学习工作路径、做能让自己注意力集中的软件研究,写这个博客而不纠结于内容的错别字(我还是会定期修改的)。我有个观点,那些与众不同的时刻(可以称之为仪式感时刻)从事后看,大多平平无奇,而巨大的改变的时候在改变发生之时都是平常无比的。我希望未来回头看的时候,现在是一个绝大变化或者至少是个特别的时刻。

start my AI side project with cf

准备开始我的AI项目了

读了两本书,感觉找回了当初“开卷有益”的感觉。从图书馆借书其实非常的方便,这让我想起了大学的时候,那会儿就是每天每天不停的看书。很多学到的东西收益终身。

这是近期读的其中一本,来自学校图书馆

现在要开始新的征程了,东撞西碰的回顾这么多年,发现github是个非常好的网站,即使几度放弃,结果,最终发现,最可控也最方便记录的居然是这个小小的静态博客。不知道有没有精力能把google.blog上的文章搬过来,也许这个目录未来会很大,不过,也许我也写不了那么多内容吧,谁知道呢。借助cloudflare的cdn和pages换了一个独立域名,发现意外的顺畅……再次感叹如果有好的IT基础生态,喜欢“折腾geek”得是每天都生活在幸福中吧。

一台坏掉的电脑,最后没有修好

在经过多次尝试和思考后,最后想着,要不先选择cloudflare这个平台(腾讯云上已经开通的虚拟机还是准备维持着),尝试开始新的项目,担忧也不是没有,只是希望这次能是个有反馈的长赛道。

后续的文章还是编号吧,这样便于管理,看了书,下一步就是熟悉各类项目了,先从记事本开始也许是个不错的主意。

某天在咖啡厅

在一个咖啡厅重启了博客

感觉每次写下博客总是在“重启”……都是更换平台,或者间隔好久,希望能把这次更换平台算到最后一次。

AI学习开始了

一年前,我在kaggle上学习课程,同样是一年前,我开始学习react,如果回顾一下过去,我发现自己依然是“乱冲乱撞”。不过,确实收获了很多内容,这些学到的东西也许哪天能发挥作用。比如,了解了ts,发现了几乎是我梦寐以求的编程语言,顺路也了解了函数式编程。

另一个好消息是,2023年年初,AI应用爆发了,也许是个新的机会,如果我能抓住或者至少能利用起来就好了。依然希望我的未来能有更好的故事。

家里的好消息

Rain考上大学了,真的是非常好的消息,全家人都开心。终于体会到那种我还把她当小姑娘但是其实已经是大孩子的感觉了。再有4年,小Rain也毕业了,那会儿会怎么样呢?3月的最后一天知道这个消息的,就把这天当作纪念日吧。

生活中充满了小惊喜

生活中的小惊喜总是不断出现,比如,去买个蛋糕碰到了过家家的联名。

在好利来拍到的照片

虽然,有时下雨不过总有开心的事情,对了,在妻子的帮助和鼓励下,我开始准备发展一些副业,也许这是新的难以想象的神奇经历的的开始。

公司窗外景色

学校的面条意外的好吃,吃了好多天,我还开玩笑的封这个面条为“天下第一面”,想起来去年的时候,想吃都吃不到。如果要说什么是小确幸的话,这个面条当之无愧吧。

小确幸之天下第一面

找到了好玩的游戏

买了《密特罗德究极重制版》,真的想把这种感觉记录下来。

密特罗德究极重制版

游戏中的氛围非常有沉浸感,不断的升级、跑路、探索,果然是经典,能相遇太好了。目前游戏还没通关,准备单开一篇聊聊感受。

我的typescript学习笔记

前言

“typescript在运行时的类型已经不存在了。所以,虽然我在request.params中可以很好的推断获得number,但是当在prisma的where中进行调用的时候还是会出现类型错误。这个坑浪费了我1个小时。” 以上是我在某个时间点写下的一段笔记,现在看来我已经看不懂了^_^,不过还是以这句话来开头,这样可以让我好好记录一下我的typescript学习,回顾我在.net技术栈上学习的经历,进入新的学习过程。

谓词保护

我在静下心来看一个项目的代码的时候,看到了这样一个函数。

1
2
3
export default function isVoid(data: unknown): data is null | undefined {
return data === null || data === undefined
}

函数非常简单,用途也非常明确,一眼就看懂了。不过”data is null | undefined”这个返回值类型让我非常意外,我其实在细节上并没有看懂。这个时候我的深究之魂,其实教程和容易找到。

看项目源码

最近在看remix.run2.8的教程视频,结合之前看的篇博客教程,感觉非常的有意思。remix官方通讯录应用教程产品Remix入门实战小册子这两个示例代码非常干净,基于他们可以开始直接启动我的项目,一步一个脚印的开始我的边缘计算环境应用的开发了。给自己的小目标是先只考虑用cf提供的东西,确定有需要的情况再引入复杂的组件。

开启了新的项目,在项目中学习

为了学好这个唯一的前后端统一框架,开了一个新的项目用来学习。依然是一个CMS类网站开始,但是这次尝试使用边缘计算的框架构建一个稳定的运行的网站。首先第一步,是克服之前的短板,通过tailwind先把界面做的好看一些,别太心急的解决后端问题。

未完待续

心境转变了一次记录

心境变化的起因

虽然很多时候,有“差生文具多”的嫌疑,我自己的google blog其实也没有太多问题(只是访问不了而已)。不过还是花了不到一个小时的时间把这个博客架设起来了~

我的github页面

起因非常突然,今天突然看到了我的github绿色马赛克多了(如上图),我意识到自己最近一段时间状态不错😌。想着把博客也转过来吧,把笔记本里沉睡的一些东西写出来。虽然有点担心自己写的东西不成熟,也许日后看来是胡言乱语,但是想着还是公开出来比较好。未来可以整理吗~~

我沉迷typescript了

最近,开始痴迷了typescript和对对应的前端开发,react,next.js,vscode,github,等等很多东西让我有点静下心来了。有点点收获,比如,发现在ts中,reduce真的可以完全代替循环存在,于是乎,写出了以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
const FitInfo = (carList: CarItem[]) => {
const combine = (years: string[]): string => {
const year_combine = years.reduce((acc, year) => {
if (acc === '') return year
const left = acc.slice(0, acc.lastIndexOf(',') + 1 + 4)
const right = acc
.slice(acc.lastIndexOf(',') + 1, acc.length)
.slice(-4)
if (Number(year) - Number(right) === 1) return left + '-' + year
if (Number(year) - Number(right) > 1) return acc + ',' + year
return acc
}, '')
return year_combine
}
const description = sort(carList)
.asc([(u) => u.make_name, (u) => u.model_name, (u) => u.year_name])
.map((v) => {
return {
carname: v.make_name + ' ' + v.model_name,
year: v.year_name,
}
})
.reduce((acc, item) => {
if (
!acc.some((it): boolean => {
return it.carname === item.carname
})
) {
acc.push({ carname: item.carname, year: [item.year] })
} else {
const obj = acc.find((it) => it.carname === item.carname)
obj?.year.push(item.year)
}
return acc
}, [] as { carname: string; year: string[] }[])
.reduce((acc, item) => {
return acc === ''
? item.carname + ' ' + combine(item.year)
: acc + ';' + item.carname + ' ' + combine(item.year)
}, '')
return description
}

我自己突然有些联想,长辈提过他上学的时候就是学习的lisp,不知道能否和他交流(大概率是不行吧🙍‍♂️)。lisp把数据和程序混在一起。我再看这段代码,循环完全是用reduce实现的,也许真的存在严禁证明for可以是不必要的。map、reduce就可以完成遍历操作。在我的程序中,为了实现目标,我引入了很多中间神奇的数据结构(指的是{ carname: string; year: string[] }),也许这就是数据和程序混在一起的感觉?利用数据结构来实现循环目标?不清楚了,希望我也能有朝一日接触到学院派的内容。当然,希望接触目标的时候能有足够的实践:比如,写个智能合约😊。

大概就是这么多,有点点困了,指针过了12点了,晚安。

开始了我的kaggle学习

学习的背景

感谢我的妻子来到我的生活,她真的是非常有智慧的女性,我感觉治愈了有点点在低谷的我。
在她的鼓励下,我重新开始看kaggle,居然顺利学完了所有的入门课程,现在开始关注一些比赛。
我的工作推进虽然缓慢,不过我内心平静了很多,感觉可以慢慢推进做一些事情了,虽然现在,偶尔还是很困并且容易劳累,也许我该健身一下。
又是个碎碎念的博客呢。
生活的中的细节多了,我目前也能静下来了,和形而上学和解了,未来也许可以写出来不错的文章。
准备做甜品的过程
最终成品
放张图记录一下最近的生活吧~

相关信息

原文地址:开始了我的kaggle学习