飞书 Task 与 AI 工作流

我的飞书,正在被 AI 接管:Task 一下,文档自己长出来

我的飞书,正在被 AI 接管:Task 一下,文档自己长出来 最近我重读了一篇文章,题目很直接,《我的飞书被AI“接管”了》。文章里讲的事很有代表性:查资料、建多维表格、看妙记、做群聊总结、创建日程和任务,这些动作一旦被封装成命令,AI 就能直接调度。 我读完后的真正感受,是另一层判断。 飞书里最先被 AI 改写的,可能不是聊天窗口,也不是单篇文档初稿。更值得重视的,是 Task 到文档之间那段原本很碎、很脏、很耗时间的执行链路。 今天我正好做了一次很典型的实操。 我把一份脱敏后的高风险 AI 合规手册拆成了一组可执行 Task,让 AI 在飞书表格里完成结构化整理、字段补写和结果回填。做完以后,我越来越确定,飞书一旦变成可调用的命令系统,它就会从“协作软件”往“执行界面”再走一步。 CLI(Command Line Interface):用文本命令直接调用系统能力的接口。可以把它理解成“跳过按钮,直接告诉软件做什么”。 Feishu CLI:把文档、表格、Task、妙记、日程等能力封装成命令之后,AI 就能在飞书内部跨对象执行动作。 一、我为什么开始重新看飞书 CLI 过去很多人聊 AI 办公,关注点常常停在“能不能写一段话”“能不能总结一页内容”。这当然有价值,但这还只是外围。 飞书 CLI 真正让我兴奋的地方,在于它把飞书的协作对象都变成了可编排资源。 原来需要人手点来点去的动作,现在可以被 AI 串起来: 先查资料 再建表格或文档 然后补字段、改结构、做汇总 最后把结果写回系统里 这时 AI 干的,就不再只是“生成一段文本”。它开始接住一小段工作流。 《我的飞书被AI“接管”了》那篇文章,其实已经把这个方向点出来了。里面提到的场景非常典型: 用命令查资料 让 AI 创建多维表格 让 AI 调取飞书妙记并整理内容 总结群聊里的高价值信息 直接创建日程和任务 再和其他 CLI 串联,接外部信息源 这些场景放在一起看,会得出一个很重要的结论: 飞书正在从“人点按钮的地方”,变成“AI 可以执行动作的地方”。 二、一次真实 Task,足够说明问题 我今天做的事情,经过脱敏后,可以概括成这样: 我先把一份面向高风险 AI 系统的合规手册,拆成了 16 个 Task。每个 Task 都对应一个明确问题和一个交付方向,覆盖数据质量、风险管理、透明度、人工监督、网络安全、质量管理体系等章节。 ...

April 23, 2026 · 2 min · 293 words · s-ai-unix
minGPT:300行代码读懂GPT原理

Andrej Karpathy 的 minGPT:300行代码读懂GPT原理

2017 年 Transformer 提出后,OpenAI 在 2018 年沿着 decoder-only 路线做出了 GPT,并在 GPT-2、GPT-3、GPT-4 上不断放大规模,验证了自回归预训练的威力。问题是,工业代码通常太大,关键细节被工程封装遮住了。 如果你想从代码层面真正看懂 GPT,Andrej Karpathy 的 minGPT 几乎是最短路径:不到 300 行,就把核心机制完整串起来。 GPT(Generative Pre-trained Transformer):一种 decoder-only 的自回归语言模型,本质是“给定前文预测下一个 token”。可以想象成超大规模自动补全系统。它重要在于同一目标函数就能覆盖写作、问答和代码生成。 一、GPT 的本质:预测下一个词 在深入代码前,先抓住任务本质。你看到“他推开那扇沉重的”,大脑会自动补“门”。GPT 做的就是这种 next-token 预测,只是它把这件事做到了海量语料和超大参数规模。 用数学语言表达,GPT 建模的是条件概率分布: $$ P(x_t | x_1, x_2, …, x_{t-1}) $$ 给定前 $t-1$ 个词,模型输出第 $t$ 个词的概率分布;不断重复这个过程,就得到完整生成。 自回归(Autoregressive):每一步只用历史信息预测下一步。可以想象成边写边续句。它重要在于训练目标和生成过程完全一致。 GPT 通过 next-token prediction 学习,不是随机挖空,而是把序列整体右移一位: $$ \text{input}=(x_1, x_2, \ldots, x_{T-1}), \quad \text{target}=(x_2, x_3, \ldots, x_T) $$ 模型每一步都预测“下一个 token”,再用交叉熵计算损失。这种训练方式既简单又有效,让 GPT 能从海量文本中自动学习语言规律。 Teacher Forcing:训练时用真实上文而不是模型自己的上一步输出。可以想象成每一步都给参考答案前缀。它重要在于让训练更稳定、收敛更快。 ...

February 16, 2026 · 6 min · 1199 words · s-ai-unix
抽象的神经网络图案

大语言模型:为什么AI能这么快、这么聪明地回答问题

引言:对话的奇迹 你有没有试过和ChatGPT、Claude、或者国内的文心一言、通义千问对话?当你问它:“帮我写一首关于春天的诗”,或者"解释一下量子力学是什么",它几乎在几秒钟内就能给出非常棒的回答。 有时候你甚至会想:它怎么这么快?它是不是有脑子?它是不是真的"理解"我在说什么? 答案可能出乎你的意料:大语言模型其实在做一件非常简单的事情——但它把这件简单的事情做到了极致。 今天,我们就来揭开这个"魔术"的面纱。 核心思想:预测下一个词 大语言模型(Large Language Model,简称LLM)的本质,可以用一句话概括: 它做的事情就是:给定一段话,预测下一个词最可能是什么。 听起来是不是太简单了?别急,让我们看个例子。 一个简单的游戏 假设我给你这句话的前半部分: "今天天气真____" 你会怎么填空? 你可能会想到:“好”、“糟糕”、“热”、“冷”、“适合出门”……这些词都是有可能的。 再换个句子: "我要去超市买_____" 你会猜:苹果、牛奶、面包、蔬菜、日用品…… 再换个: "中国位于_____" 这个答案就很明确了:亚洲、东亚。 你看,人类也在不停地做"预测下一个词"这件事。因为我们读过很多书、说过很多话,所以当我们听到半句话时,脑子里会自动出现最可能的后续。 从简单到复杂 大语言模型就是把这个"填空游戏"玩到了极致。 它读过几百万本书、几十亿篇文章、数万亿个句子。所以当你输入一段话,它能极其精准地预测下一个词。 关键点1:它不是在"思考",而是在"计算概率" 比如你问:“什么是量子力学?” 它会计算:在"什么是量子力学?“这句话后面,最可能出现的词语是什么? 它会依次生成:“量子力学是一个____"(可能填:“理论”、“学科”、“概念”)→“理论,它描述____"(可能填:“粒子”、“微观世界”、“能量”)→……一层一层地,就生成了完整的回答。 关键点2:它不是一个词一个词地"想"出来的,而是一次性计算所有可能性 就像天气预报一样,气象台不会"猜"明天会不会下雨,而是根据大量数据"计算"出下雨的概率。大语言模型也是这样:它不是在"想"下一个词是什么,而是在"计算"所有可能的下一个词的概率。 这就是为什么它能这么快——因为这是数学计算,不是思考。 数据:从海量文本中学习 你可能会问:它凭什么知道"什么是量子力学"该怎么回答? 答案很简单:因为它"读"过关于量子力学的书。 读了多少书? GPT-3(一个著名的大语言模型)的训练数据包含: 几千本书 几百万篇维基百科文章 几十亿个网页 几百万篇学术论文 大量的代码、对话、论坛帖子 总计大约5000亿个单词。 这是什么概念?假设一个人一生能读5000本书,每本书平均10万字,那就是5000 × 10万 = 5亿个词。GPT-3读的内容是一个人1000辈子才能读完的。 学到了什么? 从这些海量文本中,它学到了: 语言规律:什么是正确的语法、什么是通顺的表达 世界知识:天为什么是蓝的、苹果是什么、历史事件怎么发生的 逻辑关系:因果关系、时间顺序、对比关系 常识推理:水往下流、太阳从东边升起、人类需要喝水 专业领域:数学、物理、编程、医学、法律…… 类比一下:这就像一个从小读遍图书馆所有书、记性特别好、理解能力超强的人。当你在对话中提到某个话题时,它能瞬间调动相关的知识来回答。 神经网络:像大脑一样的结构 你可能会想:它怎么"记住"这么多东西? 这要归功于神经网络。 什么叫"神经网络”? 神经网络是一种模仿人脑结构的数学模型。 人脑有约860亿个神经元,这些神经元之间有无数个连接。当我们学习时,神经元之间的连接会"变强"或"变弱”,从而存储信息。 神经网络也是类似的: 它有很多"人工神经元”(叫作"节点") 这些神经元之间有无数个"连接"(每个连接都有一个"权重") 当它学习时,这些"权重"会不断调整 参数:知识的存储形式 大语言模型有几千亿个参数(parameters)。 “参数"是什么?你可以把它想象成"记忆单元"或"知识存储点”。 ...

January 14, 2026 · 2 min · 284 words · s-ai-unix
ISO 26262 软件级开发

ISO 26262-6 软件级开发:编写安全的代码

引言 在汽车电子系统中,软件是实现功能安全的核心。虽然硬件提供了物理基础,但软件决定了系统如何响应、如何处理故障、如何确保安全。 想象一个真实场景:某汽车厂商的自动紧急制动系统(AEB)采用了先进的深度学习算法,能够精准识别障碍物。但是,由于软件中存在一个缓冲区溢出漏洞,导致攻击者可以通过车载信息系统远程控制制动系统,造成多起事故。 这个案例告诉我们:**软件级开发不仅要实现功能,更要确保代码的安全性、可靠性和可维护性。**这正是 ISO 26262-6 软件级开发的核心使命。 软件级开发的目标和范围 软件级开发的核心活动 ISO 26262-6 定义了软件级开发的八个核心活动: 软件安全需求(SSR)的初始化 分析系统级安全需求 软件架构的初步设计 软件安全需求清单 软件架构设计 设计软件组件的架构 定义软件组件之间的接口 评估软件架构的适用性 软件单元设计和实现 设计软件单元 编写代码 代码审查 软件单元测试 设计测试用例 执行单元测试 分析测试覆盖率 软件集成和测试 集成软件单元 执行集成测试 分析测试覆盖率 软件验证 静态分析 动态分析 回归测试 软件确认 软件在环测试(SIL) 处理器在环测试(PIL) 硬件在环测试(HIL) 软件工具置信度评估 工具分类 工具置信度评估 工具使用流程 软件级开发的输入和输出 输入 系统安全需求(SSyR):来自系统级开发 技术安全概念(TSC):来自系统级开发 硬件/软件接口规范(HSIS):来自系统级开发 软件安全需求(SSR):来自系统级开发 软件约束:性能、内存、实时性等约束 输出 软件架构设计文档:软件架构设计 软件单元设计文档:软件单元设计 源代码:实现软件功能 软件测试报告:测试结果 软件验证报告:验证结果 软件确认报告:确认结果 软件安全需求(SSR)的初始化 SSR 的来源 软件安全需求主要来自以下几个方面: 从系统级安全需求(SSyR)派生 从技术安全概念(TSC)派生 从硬件/软件接口规范(HSIS)派生 SSR 的分类 1. 功能性需求 描述软件应该实现的功能。 ...

January 8, 2026 · 7 min · 1476 words · s-ai-unix
VSCode远程开发

VScode Remote远程开发完全指南

前言 最近要给别的团队A,在AWS的EC2上面去搭建一个算法的开发环境。鉴于自己之前在AWS上都是使用的Linux,在和团队A讨论了之后,最后决定建个Linux的EC2。 但是在基本的Python和数据分析和算法开发的环境都搭建好了之后,团队A的同学又提了没有IDE,影响效率。 没有办法,得考虑是不是换个Windows的EC2了。这个时候VS Code Remote Development comes to my rescue。 试用了下来,感觉这个VS Code Remote Development是个神器啊。 什么是VScode Remote Development VScode Remote Development是VScode的一个扩展功能,允许你: 使用容器、远程机器或Windows Subsystem for Linux (WSL)作为全职开发环境 在远程环境中运行扩展和工具 使用本地VScode的所有功能,就像在本地开发一样 三种Remote模式 Remote - SSH:通过SSH连接到远程机器 Remote - Containers:使用Docker容器作为开发环境 Remote - WSL:连接到Windows上的Linux子系统 本文主要介绍Remote - SSH,这是最常用的模式。 为什么使用Remote Development 传统远程开发的痛点 没有IDE:只能使用vim或emacs,学习曲线陡峭 文件传输麻烦:需要频繁使用scp或rsync 调试困难:无法使用图形化调试工具 本地和远程环境不一致:容易产生"在我机器上能跑"的问题 协作困难:难以分享开发环境 Remote Development的优势 完整的IDE体验:使用本地VScode连接远程服务器 无缝的文件操作:直接编辑远程文件,就像本地文件一样 强大的调试功能:完整的断点、变量查看等功能 环境一致性:直接在远程环境中开发 扩展支持:大部分扩展都可以在远程环境运行 安装和配置 1. 系统要求 本地机器: Windows 7/8/10/11 macOS 10.12+ Linux (Desktop) 远程机器: 运行SSH服务器 可以是Linux、macOS或其他Unix-like系统 2. 安装扩展 在本地VScode中安装"Remote - SSH"扩展: ...

July 24, 2019 · 4 min · 722 words · s-ai-unix
R语言统计分析

R语言实用技巧与数据分析实践

前言 R语言是专为统计分析和数据可视化而设计的编程语言,在数据科学、生物信息学、金融分析等领域有着广泛的应用。本文将分享R语言在数据分析中的实用技巧和最佳实践。 向量操作 处理NA值 在R语言中,NA(Not Available)表示缺失值。正确处理NA值是数据清洗的重要步骤。 过滤NA值 如果我们有一个vector叫x,x的值中有NA,如果我们想要过滤掉x中的NA,并把过滤后的结果赋值给变量y: # 创建包含NA的向量 x <- c(1, 2, NA, 4, 5, NA, 7, 8, NA, 10) # 过滤NA值 y <- x[!is.na(x)] print(y) # [1] 1 2 4 5 7 8 10 组合条件过滤 如果我们再想找出y中元素大于0的元素: y[y > 0] # [1] 1 2 4 5 7 8 10 以上两步合在一起: # 方法1:先过滤NA再过滤值 y <- x[!is.na(x)] result <- y[y > 0] # 方法2:一步完成 result <- x[!is.na(x) & x > 0] 常见错误 如果我们直接使用x[x > 0]是不可行的,会得到如下的包含NA值的一个vector: x[x > 0] # [1] 1 2 NA 4 5 NA 7 8 NA 10 原因:NA与任何值的比较结果都是NA,所以NA会保留在结果中。 解决方法:总是先检查NA,再做其他操作。 # 错误方式 result <- x[x > 0] # 正确方式 result <- x[!is.na(x) & x > 0] 矩阵操作 创建矩阵 创建一个4行5列的matrix,包含的数值是从1到20: ...

July 5, 2019 · 5 min · 940 words · s-ai-unix
Python数据分析

Python数据分析完整指南:NumPy、Pandas与可视化实战

Python数据分析生态系统包含了多个强大的库,它们各自承担不同的职责。本文将整合NumPy、Pandas、Matplotlib和Seaborn的核心功能,提供一份完整的数据分析实战指南。 环境配置与最佳实践 Jupyter Notebook优化设置 在Mac上使用Jupyter时,通过以下配置可以显著提升绘图质量。在~/.ipython/profile_default/ipython_kernel_config.py中添加: c.IPKernelApp.matplotlib = 'inline' c.InlineBackend.figure_format = 'retina' 绘图样式设置 使用更美观的绘图样式: import matplotlib.pyplot as plt plt.style.use('seaborn') # 查看所有可用样式 print(plt.style.available) 推荐使用的样式包括:'seaborn'、'ggplot'、'bmh'等。 核心库导入 import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn.datasets import load_iris NumPy:高效数值计算基础 NumPy是Python数据分析的基石,提供了高性能的多维数组和数值计算功能。 数组创建与基本操作 # 加载示例数据 iris = load_iris() df = pd.DataFrame(iris.data, columns=iris.feature_names) df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label'] # 选择特定列 data = np.array(df.iloc[:100, [0, 1, -1]]) print(f"DataFrame shape: {df.shape}") # (150, 5) print(f"Data shape: {data.shape}") # (100, 3) 数据提取技巧 从ndarray提取数据和标签: # 假设最后一列是标签,前面是特征 X = dataset[:, 0:-1] # 或 dataset[:, 0:8] y = dataset[:, 8] 从DataFrame提取数据和标签: X, y = data.iloc[:, :-1], data.iloc[:, -1] 分离特征和标签: # 获取前两列特征和最后一列标签 X, y = data[:, :-1], data[:, -1] print(f"X shape: {X.shape}") # (100, 2) print(f"y shape: {y.shape}") # (100,) 数组切片的重要区别 理解切片的维度差异至关重要: ...

July 4, 2019 · 6 min · 1161 words · s-ai-unix
Python开发环境

Python开发环境配置与管理最佳实践

Python开发环境的合理配置是项目成功的基础。本文将整合虚拟环境管理、包安装优化和运行时配置三个关键主题,帮助你构建高效、规范的Python开发环境。 一、使用pipenv管理虚拟环境 pipenv是Python官方推荐的包管理工具,它结合了pip和virtualenv的功能,为项目提供依赖管理和虚拟环境隔离。 1.1 导出现有环境的依赖 当你在某个Python环境中已经安装了多个包,需要将其迁移到新环境时,可以使用pip freeze命令导出依赖列表: pip freeze > requirements.txt 这个命令会生成一个包含所有已安装包及其版本的requirements.txt文件,是环境迁移的第一步。 1.2 使用pipenv创建项目环境 创建新项目并初始化pipenv环境的完整流程: # 创建项目目录并移动依赖文件 mkdir myproject && mv requirements.txt myproject && cd myproject # 指定Python版本创建虚拟环境 pipenv --python 3.6 # 激活虚拟环境 pipenv shell # 安装依赖(开发模式) pipenv install --dev 命令说明: pipenv --python 3.6:指定Python 3.6创建虚拟环境 pipenv shell:激活虚拟环境并进入子shell pipenv install --dev:安装requirements.txt中的所有依赖,包括开发依赖 1.3 虚拟环境管理 pipenv会在项目目录中创建Pipfile和Pipfile.lock文件,用于精确记录依赖关系。虚拟环境默认存储在~/.local/share/virtualenvs目录下。 删除虚拟环境: # 方法1:使用pipenv命令(推荐) pipenv --rm # 方法2:手动删除虚拟环境目录 rm -rf ~/.local/share/virtualenvs/你的项目名称-XXXXX 1.4 pipenv最佳实践 始终使用虚拟环境:避免全局污染,保持项目依赖隔离 提交Pipfile和Pipfile.lock:确保团队成员使用相同的依赖版本 分离开发和生产依赖:使用--dev参数区分环境 定期更新依赖:使用pipenv update保持依赖最新 二、使用国内镜像源加速包安装 PyPI官方服务器在国外,直接访问速度较慢。使用国内镜像源可以显著提升包安装速度。 ...

May 31, 2019 · 4 min · 681 words · s-ai-unix
开发工具与编程

开发工具与编程技巧集锦

优秀的开发者不仅要掌握语言本身,更要熟悉各种开发工具和编程技巧。本文汇集了多种语言的实用技巧和工具,帮助你提升开发效率和代码质量。 JavaScript实用技巧 数组操作 基本排序 // 数字数组排序(从小到大) function compare(num1, num2) { return num1 - num2; } var nums = [3, 1, 2, 100, 4, 200]; nums.sort(compare); console.log(nums); // [1, 2, 3, 4, 100, 200] // 从大到小排序 function compareDesc(num1, num2) { return num2 - num1; } nums.sort(compareDesc); console.log(nums); // [200, 100, 4, 3, 2, 1] 注意:JavaScript的sort()方法默认将元素转换为字符串排序,所以对数字需要自定义比较函数。 迭代器方法 // map:创建新数组 function first(word) { return word[0]; } var words = ["for", "your", "info"]; var acronym = words.map(first); console.log(acronym.join("")); // "fyi" // 数值计算 var numbers = [1, 2, 3, 4, 5]; var doubled = numbers.map(x => x * 2); console.log(doubled); // [2, 4, 6, 8, 10] filter过滤 // 筛选及格成绩 function passing(num) { return num >= 60; } var grades = []; for (var i = 0; i < 20; i++) { grades[i] = Math.floor(Math.random() * 101); } var passGrades = grades.filter(passing); console.log("全部成绩:", grades); console.log("及格成绩:", passGrades); // 筛选偶数 var nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; var evens = nums.filter(n => n % 2 === 0); console.log(evens); // [2, 4, 6, 8, 10] reduce累加 // 数组求和 var numbers = [1, 2, 3, 4, 5]; var sum = numbers.reduce((total, num) => total + num, 0); console.log(sum); // 15 // 数组最大值 var max = numbers.reduce((a, b) => Math.max(a, b)); console.log(max); // 5 // 统计字符出现次数 var str = "hello world"; var charCount = str.split('').reduce((count, char) => { count[char] = (count[char] || 0) + 1; return count; }, {}); console.log(charCount); // {h: 1, e: 1, l: 3, o: 2, ' ': 1, w: 1, r: 1, d: 1} some和every // some:是否存在满足条件的元素 var numbers = [1, 2, 3, 4, 5]; var hasEven = numbers.some(n => n % 2 === 0); console.log(hasEven); // true // every:是否所有元素都满足条件 var allPositive = numbers.every(n => n > 0); console.log(allPositive); // true var allGreaterThanThree = numbers.every(n => n > 3); console.log(allGreaterThanThree); // false forEach遍历 var colors = ["red", "green", "blue"]; colors.forEach((color, index) => { console.log(`${index}: ${color}`); }); // 输出: // 0: red // 1: green // 2: blue 二维数组操作 计算学生平均分 // 计算每个学生的平均分 var grades = [ [89, 77, 78], [76, 82, 81], [91, 94, 89] ]; var total = 0; var average = 0.0; for (var row = 0; row < grades.length; row++) { for (var col = 0; col < grades[row].length; col++) { total += grades[row][col]; } average = total / grades[row].length; console.log("Student " + (row + 1) + " average: " + average.toFixed(2)); total = 0; average = 0.0; } // 输出: // Student 1 average: 81.33 // Student 2 average: 79.67 // Student 3 average: 91.33 计算科目平均分 // 计算每门考试的平均分 var grades = [ [89, 77, 78], [76, 82, 81], [91, 94, 89] ]; var total = 0; var average = 0.0; for (var col = 0; col < grades[0].length; col++) { for (var row = 0; row < grades.length; row++) { total += grades[row][col]; } average = total / grades.length; console.log("Test " + (col + 1) + " average: " + average.toFixed(2)); total = 0; average = 0.0; } // 输出: // Test 1 average: 85.33 // Test 2 average: 84.33 // Test 3 average: 82.67 对象操作 按键排序对象 // 按对象的某个键排序 var obj = [ {name: "Alice", age: 25}, {name: "Bob", age: 20}, {name: "Charlie", age: 30} ]; obj.sort((a, b) => a.age - b.age); console.log(obj); // [ // {name: "Bob", age: 20}, // {name: "Alice", age: 25}, // {name: "Charlie", age: 30} // ] 对象解构 // 解构赋值 var person = {name: "Alice", age: 25, city: "New York"}; var {name, age} = person; console.log(name); // "Alice" console.log(age); // 25 // 嵌套解构 var data = { user: { name: "Bob", address: { city: "Boston" } } }; var {user: {address: {city}}} = data; console.log(city); // "Boston" jQuery实用技巧 jQuery是与否 // 检查jQuery是否加载 if (typeof jQuery === 'undefined') { console.log('jQuery not loaded'); } else { console.log('jQuery loaded'); } // 检查元素是否存在 if ($('#myElement').length) { console.log('Element exists'); } jQuery引入方式 <!-- 方式1:从CDN引入 --> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <!-- 方式2:本地文件 --> <script src="/js/jquery-3.6.0.min.js"></script> <!-- 方式3:使用包管理器 --> <!-- npm install jquery --> <script src="./node_modules/jquery/dist/jquery.min.js"></script> <!-- 方式4:RequireJS --> <script> require(['jquery'], function($) { $(document).ready(function() { console.log('jQuery loaded via RequireJS'); }); }); </script> Python数据结构与算法 链表实现 基础链表 class Node: def __init__(self, value): self.value = value self.next = None def __str__(self): return str(self.value) class LinkedList: def __init__(self): self.head = None self.tail = None def addNode(self, value): node = Node(value) if self.head is None: self.head = node self.tail = node else: self.tail.next = node self.tail = node def __str__(self): if self.head is not None: index = self.head nodeStore = [str(index.value)] while index.next is not None: index = index.next nodeStore.append(str(index.value)) return "LinkedList [ " + "->".join(nodeStore) + " ]" return "LinkedList []" def generateLinkedList(numArray): linkedlist = LinkedList() for i in range(len(numArray)): linkedlist.addNode(numArray[i]) return linkedlist # 使用示例 list1 = generateLinkedList([2, 4, 3]) print(list1) # LinkedList [ 2->4->3 ] 链表相加 class ListsSum: def addLists(self, l1, l2): p1 = l1.head p2 = l2.head carry = 0 linkedlist_sum = LinkedList() while (p1 is not None) or (p2 is not None) or (carry != 0): dig_sum = carry if p1 is not None: dig_sum += p1.value p1 = p1.next if p2 is not None: dig_sum += p2.value p2 = p2.next linkedlist_sum.addNode(dig_sum % 10) carry = dig_sum // 10 return linkedlist_sum # 使用示例 solution = ListsSum() list1 = generateLinkedList([2, 4, 3]) # 342 list2 = generateLinkedList([5, 6, 4]) # 465 print(solution.addLists(list1, list2)) # 807: LinkedList [ 7->0->8 ] 栈的实现 class Stack: def __init__(self): self.items = [] def push(self, item): self.items.append(item) def pop(self): if not self.is_empty(): return self.items.pop() def is_empty(self): return len(self.items) == 0 def peek(self): if not self.is_empty(): return self.items[-1] def size(self): return len(self.items) # 使用示例 stack = Stack() stack.push(1) stack.push(2) stack.push(3) print(stack.pop()) # 3 print(stack.peek()) # 2 print(stack.size()) # 2 算法实践技巧 Java算法练习提示 使用Scanner处理输入 Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); String str = scanner.nextLine(); 数组初始化技巧 // 动态数组 ArrayList<Integer> list = new ArrayList<>(); // 固定大小数组 int[] arr = new int[n]; // 二维数组 int[][] matrix = new int[m][n]; 常用工具方法 // 数组排序 Arrays.sort(arr); // 数组转字符串 Arrays.toString(arr); // 填充数组 Arrays.fill(arr, value); Perl技巧集锦 Perl One-Liners 文本处理 # 删除重复行 perl -ne 'print unless $a{$_}++' file.txt # 查找重复行 perl -ne 'print if $a{$_}++' file.txt # 添加行号 perl -ne 'print "$. $_"' file.txt # 反转行顺序 perl -e 'print reverse <>' file.txt # 随机排序行 perl -e 'print shuffle <>' file.txt 数值计算 # 计算列的总和 perl -lane '$sum += $F[0]; END { print $sum }' file.txt # 计算平均值 perl -lane '$sum += $F[0]; $count++; END { print $sum/$count }' file.txt # 查找最大值 perl -lane '$max = $F[0] if !defined $max || $F[0] > $max; END { print $max }' file.txt Perl高级特性 静态变量 # 使用state定义静态变量(Perl 5.10+) use feature 'state'; sub counter { state $count = 0; return ++$count; } print counter(); # 1 print counter(); # 2 print counter(); # 3 # 老版本方法 sub counter_old { my $count; $count ||= 0; return ++$count; } 匿名子例程 # 创建闭包 sub create_counter { my $count = 0; return sub { return ++$count; }; } my $counter1 = create_counter(); my $counter2 = create_counter(); print $counter1->(); # 1 print $counter1->(); # 2 print $counter2->(); # 1 数据结构实现对比 链表的多种实现 Perl链表实现 package LinkedList; sub new { my $class = shift; my $self = { head => undef, tail => undef, }; bless $self, $class; return $self; } sub add_node { my ($self, $value) = @_; my $node = {value => $value, next => undef}; if (!defined $self->{head}) { $self->{head} = $node; $self->{tail} = $node; } else { $self->{tail}{next} = $node; $self->{tail} = $node; } } C链表实现 typedef struct Node { int value; struct Node* next; } Node; typedef struct LinkedList { Node* head; Node* tail; } LinkedList; void addNode(LinkedList* list, int value) { Node* node = (Node*)malloc(sizeof(Node)); node->value = value; node->next = NULL; if (list->head == NULL) { list->head = node; list->tail = node; } else { list->tail->next = node; list->tail = node; } } 线性表的顺序存储 指针实现(动态数组) typedef struct { int* data; int length; int capacity; } SeqList; void initList(SeqList* list, int capacity) { list->data = (int*)malloc(sizeof(int) * capacity); list->length = 0; list->capacity = capacity; } void insert(SeqList* list, int index, int value) { if (index < 0 || index > list->length) { return; // 索引越界 } if (list->length >= list->capacity) { // 扩容 int newCapacity = list->capacity * 2; int* newData = (int*)realloc(list->data, sizeof(int) * newCapacity); if (newData) { list->data = newData; list->capacity = newCapacity; } } // 移动元素 for (int i = list->length; i > index; i--) { list->data[i] = list->data[i - 1]; } list->data[index] = value; list->length++; } 引用实现(智能指针) #include <memory> #include <vector> class SmartList { private: std::shared_ptr<std::vector<int>> data; public: SmartList() : data(std::make_shared<std::vector<int>>()) {} void insert(int index, int value) { if (index >= 0 && index <= data->size()) { data->insert(data->begin() + index, value); } } int get(int index) const { if (index >= 0 && index < data->size()) { return (*data)[index]; } return -1; // 或抛出异常 } int size() const { return data->size(); } }; 二叉树遍历 递归实现 class TreeNode: def __init__(self, value): self.value = value self.left = None self.right = None def preorder_traversal(node): """前序遍历:根-左-右""" if node: print(node.value) preorder_traversal(node.left) preorder_traversal(node.right) def inorder_traversal(node): """中序遍历:左-根-右""" if node: inorder_traversal(node.left) print(node.value) inorder_traversal(node.right) def postorder_traversal(node): """后序遍历:左-右-根""" if node: postorder_traversal(node.left) postorder_traversal(node.right) print(node.value) 非递归实现(使用栈) def preorder_iterative(root): """前序遍历非递归实现""" if not root: return stack = [root] while stack: node = stack.pop() print(node.value) # 先右后左,保证左子树先处理 if node.right: stack.append(node.right) if node.left: stack.append(node.left) def inorder_iterative(root): """中序遍历非递归实现""" stack = [] current = root while current or stack: # 到达最左节点 while current: stack.append(current) current = current.left current = stack.pop() print(current.value) current = current.right 实用编程技巧 文件批量操作 Perl批量重命名 use strict; use warnings; use Cwd; my $target_dir = getcwd(); opendir(my $dh, $target_dir) || die "can't opendir $target_dir: $!"; my @files = grep { /\w/ && -f "$_" && !/^\./ } readdir($dh); for (@files) { my $file = $_; # 示例:[Alex_Holmes]_Hadoop_in_Practice(BookZZ.org).pdf # 转换为:Hadoop_in_Practice.pdf if (/^(?:\[[\S\s]+\])([\S\s]+)(?:\([\S\s]+\))\.pdf$/) { my $new_name = $1 . ".pdf"; rename($file, $new_name) || die("error in renaming: $!"); } } Python批量操作 import os import re def batch_rename(directory): pattern = re.compile(r'\[.*?\](.*?)\(.*?\)\.pdf$') for filename in os.listdir(directory): match = pattern.match(filename) if match: new_name = match.group(1) + '.pdf' old_path = os.path.join(directory, filename) new_path = os.path.join(directory, new_name) os.rename(old_path, new_path) print(f"Renamed: {filename} -> {new_name}") batch_rename('.') 文本处理技巧 删除^M字符 # Vim中删除DOS换行符 :%s/^M//g # ^M输入方法:Ctrl+V,然后Enter # Perl脚本删除^M并删除注释 open($IN, $ARGV[0]) or die "in: $@"; open($OUT, ">", $ARGV[0] . ".new") or die "out: $@"; while (<$IN>) { my $line = $_; $line =~ s/(\/\/.*)//g; # 删除C风格注释 $line =~ s/\r//g; # 删除^M print $OUT $line; } close($IN); close($OUT); # 转换并替换原文件 $command = "mv $ARGV[0].new $ARGV[0] && chmod 777 $ARGV[0] && dos2unix $ARGV[0]"; system($command); 命令行工具技巧 按行长度排序 # 按行长度从长到短排序 cat file.txt | awk '{ print length($0) " " $0; }' | sort -r -n | cut -d ' ' -f 2- # 按行长度从短到长排序 cat file.txt | awk '{ print length($0) " " $0; }' | sort -n | cut -d ' ' -f 2- 提取公共行 # 查找多个文件中的公共行 grep -F -x -f file1 file2 file3 # 查找在file1中但不在file2中的行 grep -F -x -v -f file2 file1 统计最常用命令 # 查看最常用的10个命令 history | awk '{a[$2]++} END {for(i in a) {print a[i]" "i}}' | sort -rn | head 模块化编程 创建可重用模块 # MyUtils.pm package MyUtils; use strict; use warnings; use Exporter 'import'; our @EXPORT_OK = qw(add multiply); sub add { my ($a, $b) = @_; return $a + $b; } sub multiply { my ($a, $b) = @_; return $a * $b; } 1; # 使用模块 use MyUtils qw(add multiply); print add(2, 3); # 5 print multiply(2, 3); # 6 Python模块化 # utils.py def add(a, b): return a + b def multiply(a, b): return a * b # main.py from utils import add, multiply print(add(2, 3)) # 5 print(multiply(2, 3)) # 6 性能优化技巧 尾递归优化 // 普通递归阶乘 int factorial(int n) { if (n <= 1) return 1; return n * factorial(n - 1); } // 尾递归优化版本 int factorial_tail(int n, int accumulator) { if (n <= 1) return accumulator; return factorial_tail(n - 1, n * accumulator); } int factorial(int n) { return factorial_tail(n, 1); } 记忆化技术 # Fibonacci记忆化 from functools import lru_cache @lru_cache(maxsize=None) def fibonacci(n): if n < 2: return n return fibonacci(n - 1) + fibonacci(n - 2) # 手动实现记忆化 def fibonacci_memo(): cache = {} def fib(n): if n in cache: return cache[n] if n < 2: result = n else: result = fib(n - 1) + fib(n - 2) cache[n] = result return result return fib fib = fibonacci_memo() 小结 本文汇集了多种编程语言和工具的实用技巧: ...

August 31, 2014 · 10 min · 2011 words · s-ai-unix
多语言编程

多语言实现对比:C、Perl与Python的数据结构与算法

不同的编程语言在实现数据结构与算法时各有特点。本文将通过实际代码示例,对比C、Perl和Python三种语言在实现常见数据结构与算法时的差异,帮助开发者选择最适合的工具。 一、语言特性概览 1.1 C语言 特点: 底层语言,直接操作内存 需要手动管理内存(malloc/free) 类型系统严格 性能优异,但开发效率较低 适合系统级编程和性能敏感场景 1.2 Perl 特点: 高级脚本语言 自动内存管理 灵活的类型系统 文本处理能力强 适合快速开发和系统管理 1.3 Python 特点: 高级解释型语言 自动内存管理和垃圾回收 面向对象,语法简洁 丰富的标准库 适合快速开发和原型设计 二、栈的实现对比 2.1 C语言实现 #include <stdio.h> #include <stdlib.h> #define MAXSIZE 1000 #define OK 1 #define ERROR 0 typedef int Status; typedef int SElemType; typedef struct { SElemType data[MAXSIZE]; int top; } SqStack; /* 初始化栈 */ Status InitStack(SqStack *S) { S->top = -1; return OK; } /* 入栈 */ Status Push(SqStack *S, SElemType e) { if(S->top == MAXSIZE - 1) return ERROR; S->top++; S->data[S->top] = e; return OK; } /* 出栈 */ Status Pop(SqStack *S, SElemType *e) { if(S->top == -1) return ERROR; *e = S->data[S->top]; S->top--; return OK; } /* 获取栈顶元素 */ Status GetTop(SqStack S, SElemType *e) { if(S.top == -1) return ERROR; *e = S.data[S.top]; return OK; } int main() { SqStack s; InitStack(&s); Push(&s, 10); Push(&s, 20); Push(&s, 30); SElemType e; Pop(&s, &e); printf("Popped: %d\n", e); GetTop(s, &e); printf("Top: %d\n", e); return 0; } C语言特点: ...

August 20, 2014 · 7 min · 1447 words · s-ai-unix