Lua 第5部分 表
表( Table )是 Lua 语言中最主要(事实上也是唯一的)和强大的数据结构。 使用表,Lua语言可以以一种简单、统一且高效的方式表示数组、集合、记录和其他很多数据结构。 Lua语言也使用表来表示包( package )和其他对象。 当调用函数 math.sin 时 ,我们可能认为是“调用了 math 库中函数 sin ” ;而对于 Lua 语言来说,其实际含义是“以字符串sin ” 为键检索表 math ”。
Lua 语言中的表本质上是一种辅助数组( associative array ),这种数组不仅可以使用数值作为索引,也可以使用字符串或其他任意类型的值作为索引( nil 除外)。
Lua 语言中的表要么是值要么是变量 ,它们都是对象 ( object ) 。 如果读者对 Java 或
Scheme 中的数组比较熟悉 ,那么应该很容易理解上述概念。 可以认为,表是一种动态分配的对象,程序只能操作指向表的引用(或指针) 。 除此以外, Lua 语言不会进行隐藏的拷贝( hidden copies)或创建新的表。
我们使用构造器表达式( constructor expression )创建表,其最简单的形式是 {} :
> a={} --创建一个表然后用表的引用赋值
> k="x"
> a[k]=10 --新元素,键是"x",值是10
> a[20]="great" --新元素,键是20,值是"great"
> a["x"]
10
> k=20
> a[k]
great
> a["x"]=a["x"]+1 --修改元素"x"的值
> a["x"]
11
表永远是匿名的,表本身和保存表的变量之间没有固定的关系:
> a={}
> a["x"]=10
> b=a --'b'和'a'引用同一张表
> b["x"]
10
> b["x"]=20
> a["x"]
20
> a=nil --只有'b'仍然指向表
> b=nil --没有指向表的引用了
> a["x"]
stdin:1: attempt to index a nil value (global 'a')
> b["x"]
stdin:1: attempt to index a nil value (global 'b')
对于一个表而言,当程序中不再有指向它的引用时,垃圾收集器会最终删除这个表并重用其占用的内存。
5.1 表索引
同一个表中存储的值可以具有不同的类型索引 , 并可以按需增长以容纳新的元素 :
> a={} --空的表
> --创建1000个新元素
> for i=1,1000 do a[i]=i*2 end
> a[9]
18
> a["x"]=10
> a["x"]
10
> a["y"]
nil
请注意上述代码的最后一行 :如同全局变量一样,未经初始化的表元素为 nil ,将 nil 赋值给表元素可以将其删除。 这并非巧合,因为 Lua 语言实际上就是使用表来存储全局变量的。
当把表当作结构体使用时,可以把索引当作成员名称使用( a. name 等价于 a["name"] ) 。
因此 ,可以使用这种更加易读的方式改写前述示例的最后几行 :
> a={} --空白表
> a.x=10 --等价于a["x"]=10
> a.x --等价于a["x"]
10
> a.y --等价于a["y"]
nil
对 Lua 语言而言,这两种形式是等价且可以自由混用的;不过,对于阅读程序的人而言,这两种形式可能代表了不同的意图 。 形如 a.name 的点分形式清晰地说明了表是被当作结构体使用的,此时表实际上是由固定的、预先定义的键组成的集合;而形如a["name"] 的字符串索引形式则说明了表可以使用任意字符串作为键,并且出于某种原因我们操作的是指定的键。
初学者常常会混淆 a.x 和 a [ x ] 。 实际上, a.x 代表的是 a["x"] ,即由字符串” x ”索引的
表;而 a[x]则是指由变量 x 对应的值索引的表,例如 :
> a={}
> x="y"
> a[x]=10
> a[x]
10
> a.x --字段"x"的值(未定义)
nil
> a.y
10
>
由于可以使用任意类型索引表,所以在索引表时会遇到相等性比较方面的微妙问题。 虽然确实都能用数字 0 和字符串 ” 0 ” 对同一个表进行索引,但这两个索引的值及其所对应的元素是不同的 。 同样,字符串”+ 1 ” 、 ” 01 ” 和” 1 ” 指向的也是不同的元素 。 当不能确定表索引的真实数据类型时,可以使用显式的类型转换,强制类型转换函数为 tonumber():
> i=10;j="10";k="+10"
> a={}
> a[i]="number key"
> a[j]="string key"
> a[k]="another string key"
> a[i]
number key
> a[j]
string key
> a[k]
another string key
> a[tonumber(j)]
number key
> a[tonumber(k)]
number key
如果不注意这一点,就会很容易在程序中引人诡异的 Bug 。
整型和浮点型类型的表索引则不存在上述问题。 由于 2 和 2.0 的值相等,所以当它们被当作表索引使用时指向的是同一个表元素:
> a={}
> a[2.0]=10
> a[2.1]=20
> a[2]
10
> a[2.1]
20
更准确地说,当被用作表索引时,任何能够被转换为整型的浮点数都会被转换成整型数。 例如,当执行表达式 a[2.0]=10 时,键 2.0 会被转换为 2 。 相反,不能被转换为整型数的浮点数则不会发生上述的类型转换。
5.2 表构造器
表构造器( Table Constructor )是用来创建和初始化表的表达式,也是 Lua 语言中独有的也是最有用、最灵活的机制之一。
最简单的构造器是空构造器 {} 。 表构造器也可以被用来初始化列表,例如,下例中使用字符串" Sunday ” 初始化了 days[1] (构造器第一个元素的索引是 1 而不是 0 )、使用字符串 ” Monday ” 初始化了 days[2] ,依此类推 :
> days={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}
> print(days[4])
Wednesday
Lua 语言还提供了一种初始化记录式( record-like )表的特殊语法 :
> a={x=10,y=20}
> a["x"]
10
上述代码等价于:
> a={};a.x=10;a.y=20
不过,在第一种写法中,由于能够提前判断表的大小,所以运行速度更快。
无论使用哪种方式创建表,都可以随时增加或删除表元素:
> w={x=0,y=0,label="console"}
> x={math.sin(0),math.sin(1),math.sin(2)}
> w[1]="another field" --把键1增加到表‘w’中
> x.f=w --把键f增加到表‘x’中
> print(w["x"])
0
> print(w[1])
another field
> print(x.f[1])
another field
> w.x=nil --删除字段‘x’
> x.f.x
nil
> x.f.y
0
> x.f.label
console
在同一个构造器中,可以棍用记录式( record-styl e ) 和列表式( list-style )写法:
polyline = {color="blue",thickness=2,npoints=4,{x=0,y=0}, --polyline[1]{x=-10,y=0}, --polyline[2]{x=-10,y=1}, --polyline[3] {x=0,y=1} --polyline[4]}
> polyline = {color="blue",
>> thickness=2,
>> npoints=4,
>> {x=0,y=0},
>> {x=-10,y=0},
>> {x=-10,y=1},
>> {x=0,y=1}
>> }
> print(polyline[2].x)
-10
> print(polyline[4].y)
1
不过,这两种构造器都有各自的局限。 例如,使用这两种构造器时 ,不能使用负数索引初始化表元素, 也不能使用不符合规范的标识符作为索引 。 对于这类需求,可以使用另一种更加通用的构造器,即通过方括号括起来的表达式显式地指定每一个索引 :
> opnames = {["+"] = "add", ["-"] = "sub",
>> ["*"] = "mul",[""] = "div"}
> i=20;s="-"
> a={[i+0]=s,[i+1]=s..s,[i+2]=s..s..s}
> print(opnames[s])
sub
> print(a[22])
---
这种构造器虽然冗长,但却非常灵活 , 不管是记录式构造器还是列表式构造器均是其特殊形式。 例如,下面的几种表达式就相互等价:
{x=0,y=0} <--> {["x"]=0,["y"]=0}
{"r","g","b"} <--> {[1]="r",[2]="g",[3]="b"}
在最后一个元素后总是可以紧跟一个逗号。 虽然总是有效,但是否加最后一个逗号是可选的:
a = {[1]="r",[2]="g",[3]="b",}
这种灵活性使得开发人员在编写表构造器时不需要对最后一个元素进行特殊处理。
最后,表构造器中的逗号也可以使用分号代替,这主要是为了兼容 Lua 语言的旧版本,目前基本不会被用到 。
5.3 数组、列表和序列
如果想表示常见的数组(array )或列表( list ),那么只需要使用整型作为索引的表即可。
同时,也不需要预先声明表的大小,只需要直接初始化我们需要的元素即可:
-- 读取10行,然后保存在一个表中
a = {}
for i=1,10 doa[i] = io.read()
end
鉴于能够使用任意值对表进行索引,我们也可以使用任意数字作为第一个元素的索引 。 不过,在 Lua 语言中,数组索引按照惯例是从 1 开始的(不像 C 语言从 0 开始), Lua 语言中的其他很多机制也遵循这个惯例 。
当操作列表时,往往必须事先获取列表的长度 。 列表的长度可以存放在常量中,也可以存放在其他变量或数据结构中 。 通常,我们把列表的长度保存在表中某个非数值类型的字段中(由于历史原因,这个键通常是” n" ) 。 当然,列表的长度经常也是隐式的。 请注意,由于未初始化的元素均为 nil ,所以可以利用 nil 值来标记列表的结束。 例如, 当向一个列表中写入了 10 行数据后,由于该列表的数值类型的索引为 1,2, .. ., 10 ,所以可以很容易地知道列表的长度就是 10 。 这种技巧只有在列表中不存在空洞 ( hole )时(即所有元素均不为 nil )才有效,此时我们把这种所有元素都不为 nil 的数组称为序列 ( sequence )。
Lua 语言提供了获取序列长度的操作符 # 。 正如我们之前所看到的,对于字符串而言,该
操作符返回字符串的字节数;对于表而言,该操作符返回表对应序列的长度。 例如,可以使用如下的代码输出上例中读入的内容:
for i = 1, #a doprint(a[i])
end
长度操作符也为操作序列提供了几种有用的写法 :
print(a[#a]) --输出序列‘a’的最后一个值
a[#a] = nil --移除最后一个值
a[#a + 1] = v --把v加到序列的最后
对于中间存在空洞( nil 值)的列表而言,序列长度操作符是不可靠的,它只能用于序列(所有元素均不为 nil 的列表)。 更准确地说,序列 ( sequence ) 是由指定的 n 个正数数值类型的键所组成集合 { 1, ... , n }形成的表(请注意值为 nil 的键实际不在表中)。 特别地 ,不包含数值类型键的表就是长度为零的序列
将长度操作符用于存在空洞的列表的行为是 Lua 语言 中最具争议的内容之一。在过去几年中,很多人建议在操作存在空洞的列表时直接抛出异常 , 也有人建议扩展长度操作符的语义。 然而,这些建议都是说起来容易做起来难。 其根源在于列表实际上是一个表,而对于表来说,“长度”的概念在一定程度上是不容易理解的 。 例如,考虑如下的代码 :
a = {}
a[1] = 1
a[2] = nil --什么也没有做,因为a[2]已经是nil了
a[3] = 1
a[4] = 1
我们可以很容易确定这是一个长度为 4 、在索引 2 的位置上存在空洞的列表。 不过,对于下面这个类似的示例是否也如此呢?
a = {}
a[1] = 1
a[10000] = 1
是否应该认为 a 是一个具有 10000 个元素、 9998 个空洞的列表?如果代码进行了如下的操作:
a[10000] = nil
那么该列表的长度会变成多少?由于代码删除了最后一个元素,该列表的长度是不是变成了9999 ?或者由于代码只是将最后一个元素变成了 nil ,该列表的长度仍然是 10000 ?又或者该列表的长度缩成了 1?
另一种常见的建议是让#操作符返回表中全部元素的数量。 虽然这种语义听起来清晰且定义明确,但并非特别有用和符合直觉。 请考虑一下我们在此讨论过的所有例子,然后思考一下对这些例子而言,为什么让#操作符返回表中全部元素的数量并非特别有用 。
更复杂的是列表以 nil 结尾的情况。 请问如下的列表的长度是多少 :
a = {10,20,30,nil,nil}
请注意,对于 Lua 语言而言,一个为 nil 的字段和一个不存在的元素没有区别。 因此,上述列表与 { 10, 20, 30 } 是等价的一一其长度是 3 ,而不是 5 。
可以将以 nil 结尾的列表当作一种非常特殊的情况。 不过,很多列表是通过逐个添加各个元素创建出来的。 任何按照这种方式构造出来的带有空洞的列表,其最后一定存在为 nil的值。
尽管讨论了这么多,程序中的大多数列表其实都是序列(例如不能为nil的文件行)。 正因如此, 在多数情况下使用长度操作符是安全的。 在确实需要处理存在空洞的列表时,应该将列表的长度显式地保存起来。
5.4 遍历表
我们可以使用 pairs 迭代器遍历表中的键值对 :
> t = {10, print, x = 12, k = "hi"}
> for k, v in pairs(t) do
>> print(k, v)
>> end
1 10
2 function: 0000000063bdb1d0
x 12
k hi
受限于表在 Lua 语言中的底层实现机制,遍历过程中元素的出现顺序可能是随机的 ,相同的程序在每次运行时也可能产生不同的顺序。 唯一可以确定的是,在遍历的过程中每个元素会且只会出现一次。
对于列表而言,可以使用 ipairs 迭代器 :
> t = {10, print, 12, "hi"}
> for k, v in ipairs(t) do
>> print(k, v)
>> end
1 10
2 function: 0000000063bdb1d0
3 12
4 hi
此时 , Lua 会确保遍历是按照顺序进行的 。
另一种遍历序列的方法是使用数值型 for 循环 :
> t = {10, print, 12, "hi"}
> for k = 1, #t do
>> print(k, t[k])
>> end
1 10
2 function: 0000000063bdb1d0
3 12
4 hi
5.5 安全访问
考虑如下的情景:我们想确认在指定的库中是否存在某个函数。 如果我们确定这个库确实存在,那么可以直接使用 if lib.too then ... ;否则,就得使用形如 if lib and lib. foo then ... 的表达式 。
当表的嵌套深度变得比较深时,这种写法就会很容易出错,例如 :
zip = company and company.director and company.director.address and company.director.address.zipcode
这种写法不仅冗长而且低效,该写法在一次成功的访问中对表进行了 6 次访问而非 3 次访问 。
对于这种情景,诸如 C#的一些编程语言提供了 一种安全访问操作符( safe navigation
operator )。 在 C#中,这种安全访问操作符被记为“?. ” 。 例如,对于表达式 a ?.b ,当 a 为
nil 时,其结果是 nil 而不会产生异常。 使用这种操作符,可以将上例改写为:
zip = company?.director?.address?.zipcode
如果上述的成员访问过程中出现 nil ,安全访问操作符会正确地处理 nil 并最终返回 nil 。
Lua 语言并没有提供安全访问操作符,并且认为也不应该提供这种操作符。 一方面, Lua语言在设计上力求简单;另一方面,这种操作符也是非常有争议的,很多人就无理由地认为该操作符容易导致无意的编程错误。 不过,我们可以使用其他语句在 Lua 语言中模拟安全访问操作符。
对于表达式 a or {} ,当 a 为 nil 时其结果是一个空表。 因此 ,对于表达式 ( aor{}).b ,当 a 为 nil 时其结果也同样是nil 。 这样,我们就可以将之前的例子重写为:
zip = (((company or {}).director or {}).address or {}).zipcode
再进一步,我们还可以写得更短和更高效:
E = {} --可以在其他类似表达式中复用
...
zip = (((company or E).director or E).address or E).zipcode
确实 , 上述的语法比安全访问操作符更加复杂。 不过尽管如此 ,表中的每一个字段名都只被使用了一次,从而保证了尽可能少地对表进行访问(本例中对表仅有 3 次访问);同时,还避免了向语言中引入新的操作符。
5.6 表标准库
表标准库提供了操作列表和序列的一些常用函数。
函数 table.insert 向序列的指定位置插入一个元素 ,其他元素依次后移。 例如, 对于列表 t={10,20,30 },在调用 table.insert(t, 1, 15 )后它会变成 { 15, 10, 20, 30 } ,另一种特殊但常见的情况是调用 insert 时不指定位置, 此时该函数会在序列的最后插入指定的元素,而不会移动任何元素。 例如,下述代码从标准输入中按行读入内容并将其保存到一个序列中 :
t = {}
for line in io.lines() dotable.insert(t, line)
end
print(#t) -- 读取的行数
函数 table .remove 删除并返回序列指定位置的元素,然后将其后 的元素 向前移动填充删除元素后造成的空洞 。 如果在调用该函数时不指定位置,该函数会删除序列的最后一个元素。
借助这两个函数,可以很容易地实现栈( Stack )、 队列( Queue )和双端队列( Double
queue )。 以栈的实现为例,我们可以使用 t ={} 来表示栈, Pus h 操作可以使用table.insert(t,x ) 实现 ,Pop 操作可以使用 table.remove(t)实现,调用 table.insert(t, 1, x )可以实现在栈的顶部进行插入,调用 table.remove(t, 1 ) 可以从栈的顶部移除。 由于后两个函数涉
及表中其他元素的移动,所以其运行效率并不是特别高 。 当然,由于table 标准库中的这些函数是使用 C 语言实现的,所以移动元素所涉及循环的性能开销也并不是太昂贵。 因而,对于几百个元素组成的小数组来说这种实现已经足矣 。
Lua 5.3 对于移动表中的元素引入了一个更通用的函数 table.move(a, f, e, t ) ,调用该函数可以将表 a 中从索引 f 到 e 的元素(包含索引 f 和索引 e 对应的元素本身)移动到位置 t 上。 例如,如下代码可以在列表 a 的开头插入一个元素:
table.move(a, 1, #a, 2)
a[1] = newElement
如下的代码可以删除第一个元素 :
table.move(a, 2, #a, 1)
a[#a] = nil
应该注意,在计算机领域,移动 ( move)实际上是将一个值从一个地方拷贝 ( copy ) 到另一个地方。 因此 ,像上面的例子一样,我们必须在移动后显式地把最后一个元素删除。
函数 table.move 还支持使用一个表作为可选的参数。 当带有可选的表作为参数时 ,该函数将第一个表中的元素移动到第二个表中 。 例如, table.move(a, 1 ,#a, 1, {})返回列表 a 的一个克隆( clone )(通过将列表 a 中的所有元素拷贝到新列表中), table .move(a, 1, #a,#b + 1, b )将列表 a 中的所有元素复制到列表 b 的末尾。
相关文章:
Lua 第5部分 表
表( Table )是 Lua 语言中最主要(事实上也是唯一的)和强大的数据结构。 使用表,Lua语言可以以一种简单、统一且高效的方式表示数组、集合、记录和其他很多数据结构。 Lua语言也使用表来表示包( package &am…...
01分数规划
https://ac.nowcoder.com/acm/contest/22353/1011 并不需要高级数据结构,对答案二分即可。 假定当前二分的答案为 x x x,则 ∑ v i ∑ w i ≥ x \frac{ \sum_{v_i} }{\sum_{w_i}} ≥ x ∑wi∑vi≥x 成立时 x x x 才可能是最后的答案。 化简式…...
无人机动力系统全维度解析:技术演进、选型策略与未来趋势
一、动力系统技术理念与设计逻辑 (一)核心技术指标 能量密度:决定续航能力的关键参数,单位为 Wh/kg。当前主流锂聚合物电池能量密度约 250-300Wh/kg,氢燃料电池可达 500-800Wh/kg,航空燃油则高达 12,000W…...
重新审视中国的GB标准(44495 – 44497)
此前,我们深入探讨了中国新推出的智能互联汽车(ICV)网络安全标准GB Standard 44495-2024。我们探讨了该标准对汽车制造商的影响、与UNECE R155和ISO/SAE 21434等全球标准的一致性,以及该标准对未来汽车网络安全的意义。 然而,GB 44495-2024并…...
Linux进程控制(五)之做一个简易的shell
文章目录 做一个简易的shell预备知识代码实现运行结果 做一个简易的shell 重谈Shell shell是操作系统的一层外壳程序,帮我们用户执行指令, 获取到指令后,交给操作系统,操作系统执行完后,把执行结果通过shell交给用户…...
Apache Kafka全栈技术解析
目录 第一章 Kafka概述与核心价值 1.1 消息队列的演进与Kafka的诞生 1.2 Kafka的核心应用场景 1.3 Kafka生态全景图 第二章 Kafka核心概念与架构解析 2.1 核心概念深度剖析 2.2 Kafka架构设计精要 第三章 Kafka环境搭建与配置 3.1 单机部署实战 3.2 集群部署最佳实践 …...
结合 Flink/Spark 进行 AI 大数据处理(实时数据 + AI 推理的应用场景)
随着企业对实时智能决策的需求日益增强,将 Flink / Spark 等流批计算框架 与 大模型推理能力相结合,正在成为 AI 工业化落地的重要实践路径。本篇文章将深入介绍如何将 AI 模型集成到大数据流处理系统中,实现实时感知、智能判断与自动反馈。 1. 为什么需要“实时数据 + AI 推…...
开发PDF时,如何比较 PDF 文件
在 PDF 论坛上,“如何比较 PDF 文件”是一个经常被提到的问题。在开始之前,重要的是要明确你想要比较的内容是什么。 不同的 PDF 文件可能看起来一样吗? 是的,可能。不同的 PDF 创建工具可能会生成在视觉上完全相同的页面&#x…...
自动提取pdf公式 ➕ 输出 LaTeX
# 创建打包脚本的主内容 script_content """ from doc2x.extract_formula import extract_formula_imgs from pix2text import Pix2Text from PIL import Image import osdef main():pdf_path "your_file.pdf" # 将你的PDF命名为 your_file.pdf 并…...
abaqus二次开发python程序集
abaqus二次开发python程序集 1、设置字体背景色等2、读取模态频率并写入 csv 文件3、在两个窗口快速对比各价模态 1、设置字体背景色等 # _*_ coding:UTF-8 _*_from abaqusConstants import* def fontsize(sessionNone):#设置字体session.viewports[Viewport: 1].viewportAnno…...
高级java每日一道面试题-2025年3月23日-微服务篇[Nacos篇]-如何使用Nacos进行服务发现?
如果有遗漏,评论区告诉我进行补充 面试官: 如何使用Nacos进行服务发现? 我回答: 在Java高级面试中讨论如何使用Nacos进行服务发现时,可以从多个角度深入探讨,包括基本概念、配置步骤、代码示例以及高级特性。以下是综合了多种信息的详细回…...
k8s核心资源对象一(入门到精通)
本文将深入探讨Kubernetes中的核心资源对象,包括Pod、Deployment、Service、Ingress、ConfigMap和Secret,详细解析其概念、功能以及实际应用场景,帮助读者全面掌握这些关键组件的使用方法。 一、pod 1 pod概念 k8s最小调度单元,…...
了解 DeepSeek R1
了解DeepSeek R1 R1探索纯强化学习是否可以在没有监督微调的情况下学会推理的能力。 ‘Aha’ Moment 这种现象有点类似于人类在解决问题时突然意识到的方式,以下是它的工作原理: 初始尝试:模型对解决问题进行初始尝试识别:识别…...
【C语言】大小端字节序和字节序判断
前言: 在上章介绍了整形在内存的储存,了解了原码,反码,补码,知道了整数在内存的储存一般是补码,解决了负数相加的问题。 那么在本章为大家讲解一下大小端字节序。 一那字节序是什么呢? 字节…...
DrissionPage移动端自动化:从H5到原生App的跨界测试
一、移动端自动化测试的挑战与机遇 移动端测试面临多维度挑战: 设备碎片化:Android/iOS版本、屏幕分辨率差异 混合应用架构:H5页面与原生组件的深度耦合 交互复杂性:多点触控、手势操作、传感器模拟 性能监控:内存…...
ARM 汇编启动代码详解:从中断向量表到中断处理
ARM 汇编启动代码详解:从中断向量表到中断处理 引言 在嵌入式系统开发中,ARM 处理器(如 Cortex-A 系列)的启动代码是系统初始化和运行的基础。启动代码通常包括中断向量表的创建、初始化硬件状态(如关闭缓存和 MMU&a…...
笔试专题(七)
文章目录 乒乓球筐(哈希)题解代码 组队竞赛题解代码 删除相邻数字的最大分数(线性dp)题解代码 乒乓球筐(哈希) 题目链接 题解 1. 两个哈希表 先统计第一个字符串中的字符个数,再统计第二个字…...
React基础知识(一)
文章目录 概念特点React基本使用hello_react案例虚拟DOM的两种创建方式使用jsx创建使用js创建 虚拟DOM和真实DOM React jsxXMLjsx语法规则作用基本语法规则js语句和js代码babel.js作用 模块与组件模块组件 React面向组件编程函数式组件类组件 概念 react是一个将数据渲染为Htm…...
红黑树(Red-Black Tree)核心知识点与面试高频问题
红黑树(Red-Black Tree)核心知识点与面试高频问题 一、红黑树的核心性质 红黑树是一种自平衡的二叉搜索树,通过以下规则确保平衡性: 节点颜色:每个节点是红色或黑色。 根节点:根必须是黑色。 叶子节点&a…...
SpringBoot整合SSM
一、SpringBoot整合SSM SpringBoot整合SpringSpringBoot整合SpringMVCSpringBoot整合MyBatis(主要) 步骤一:创建SpringBoot工程,添加druid依赖 <!-- todo 1 添加druid连接池依赖--> <dependency><groupId>co…...
set/multiset容器
1.概念 所有元素会在插入时自动排序 set/multiset属于关联式容器,底层结构是用二叉树实现。 set不允许重复元素,multiset允许重复元素。 2. set构造和赋值 set<T> st; set(const set &st);// 拷贝构造函数 set& operator(const set &a…...
vim 编辑器 使用教程
Vim是一款强大的文本(代码)编辑器,它是由Bram Moolenaar于1991年开发完成。它的前身是Bill Joy开发的vi。名字的意义是Vi IMproved。 打开vim,直接在命令行输入vim即可,或者vim <filename>. Vim分为四种模式&a…...
去中心化固定利率协议
核心机制与分类 协议类型: 借贷协议(如Yield、Notional):通过零息债券模型(如fyDai、fCash)锁定固定利率。 收益聚合器(如Saffron、BarnBridge):通过风险分级或博弈论…...
Python高阶函数-filter
1. 基本概念 filter() 是Python内置的高阶函数,用于过滤序列中的元素。它接收一个函数和一个可迭代对象作为参数,返回一个迭代器,包含使函数返回True的所有元素。 filter(function, iterable)2. 工作原理 惰性计算:filter对象是…...
hive/doris查询表的创建和更新时间
hive查询表的创建和更新时间: SELECT d.NAME AS database_name, t.TBL_NAME AS table_name, FROM_UNIXTIME(t.CREATE_TIME) AS create_time, FROM_UNIXTIME(tp.PARAM_VALUE) AS last_ddl_time FROM metastore.TBLS t JOIN metastore.DBS d ON t.DB_ID d.DB_ID JOIN…...
40常用控件_WindowFrame的影响
window frame 的影响 如果 widget 作为一个窗口(带有标题栏,最小化,最大化,关闭按钮),那么在计算尺寸和坐标的 时候就有两种算法.包含 window frame 和 不包含 window frame. 其中x(),y0,frameGeometry(), pos(),move() 都是按照包含 window frame 的方式来计算 的. 其中 geome…...
PCB 赋能机器人技术革新:核心功能与前沿趋势
一、智能控制中枢的异构集成 采用 20 层刚挠结合板架构,搭载 NVIDIA Jetson AGX Orin SoC(100TOPS 算力),集成 64 位 ARMv8 内核与 32GB 内存,实现多模态传感器数据融合与实时决策。板载 128MB DDR4 缓存支持 μs 级响…...
unity 环形UI菜单实现方法2
在项目中需要一个环形UI并且循环往复的效果,这个方法思路为提前预设好位置,让UI根据坐标预设的移动,然后使用mask遮罩达到循环往复效果的目的。 下图分别分为了三个列表 第一个列表poslist是提前预设的位置 第二个列表为背景暂时不用看 第三个…...
Redis进阶--主从复制
目录 一、引言 二、介绍 三、解决问题 四、配置主从复制 1.复制 全量复制: 部分复制: 实时复制: 五、总结 一、引言 本篇文章将继续介绍Redis中的主从复制机制 二、介绍 主从复制是在分布式系统中实现的,希望有多个服务器…...
Redisson分布式锁:原理、使用
1. Redisson简介 Redisson是一个基于Redis的Java客户端库,提供了丰富的分布式对象和服务(如分布式锁、信号量、Map等)。其核心优势在于简化分布式锁的实现,并解决了原生Redis分布式锁的常见问题(如死锁、误删…...
Java设计模式之外观、享元、组合模式《三国争霸:模式风云录》
第一章:乱世起(外观初现) 黄巾余孽张角三兄弟操控"混沌子系统",各地流民不堪996劳役。观国隐士诸葛孔明出山,在博望坡构建首个"军师智脑": /*** 外观模式:军师智…...
设计模式之解释器模式:原理、实现与应用
引言 解释器模式(Interpreter Pattern)是一种行为型设计模式,它定义了一种语言的文法表示,并提供一个解释器来解释该语言中的句子。解释器模式适用于需要解析特定语法规则的场景,如正则表达式、SQL解析等。本文将深入…...
redis itheima
缓存问题 核心是如何避免大量请求到达数据库 缓存穿透 既不存在于 redis,也不存在于 mysql 的key,被重复请求 public Result queryById(Long id) {String key CACHE_SHOP_KEYid;// 1. redis & mysqlString shopJson stringRedisTemplate.opsFo…...
AF3 OpenFoldDataModule类setup方法解读
AlphaFold3 data_modules 模块的 OpenFoldDataLoader 类 setup 方法用于设置数据集的关键部分,负责根据不同的模式(训练、验证或预测)生成和初始化相应的数据集。 源代码: def setup(self, stage=None):# Most of the arguments are the same for the three datasets data…...
服务器报错:xxx/libc.so.6: version `GLIBC_2.32‘ not found
/lib/x86_64-linux-gnu/libc.so.6: version GLIBC_2.32 not found (required by ./aima-sim-app-main) 解决思路 根据错误信息,您的应用程序 aima-sim-app-main 和 libmujoco.so.3.1.6 库依赖于较新的 GNU C Library (glibc) 版本(如 GLIBC_2.32, GLIBC…...
FPGA状态机设计:流水灯实现、Modelsim仿真、HDLBits练习
一、状态机思想 1.概念 状态机(Finite State Machine, FSM)是计算机科学和工程领域中的一种抽象模型,用于描述系统在不同状态之间的转换逻辑。其核心思想是将复杂的行为拆解为有限的状态,并通过事件触发状态间的转移。 2.状态机…...
机试题——最少乘坐公交次数
题目描述 春节将近,小明想在节日期间逛一逛城里的 ( N ) 个著名景点。所有景点都能通过坐公交到达。需要设计一种公交路线方案,让小明能最快地逛完所有景点。 输入描述 第一行:一个整数 ( N ),表示景点数量,满足 ( …...
防孤岛保护装置在分布式光伏并网中的应用
什么是光伏的“孤岛效应” 孤岛islanding 包含负荷和电源的部分电网,从主网脱离后继续孤立运行的状态。孤岛可分为非计划性孤岛和计划性孤岛。 孤岛效应的危害 当电网侧停电检修,若并网光伏电站的逆变器仍在继续供电,维修人员不一定…...
记一次gitlab服务器负载过高问题处理
服务器上进程 /var/opt/gitlab/gitlab-rails/etc/unicorn.rb /opt/gitlab/embedded/service/gitlab-rails/config.ru 进程服务器cpu占用过高应该怎么处理 tail -f /var/log/gitlab/gitlab-rails/production.log调整 Unicorn 配置:unicorn.rb 是 Unicorn 服务器的配…...
LiT and Lean: Distilling Listwise Rerankers intoEncoder-Decoder Models
文章:ECIR 2025会议 一、动机 背景:利用LLMs强大的能力,将一个查询(query)和一组候选段落作为输入,整体考虑这些段落的相关性,并对它们进行排序。 先前的研究基础上进行扩展 [14,15],…...
【项目日记】高并发服务器项目总结
生活总是让我们遍体鳞伤, 但到后来, 那些受伤的地方一定会变成我们最强壮的地方。 -- 《老人与海》-- 高并发服务器项目总结 模块关系图项目工具模块缓冲区模块通用类型模块套接字socket模块信道Channel模块多路转接Poller模块 Reactor模块时间轮Tim…...
P1332 血色先锋队(BFS)
题目背景 巫妖王的天灾军团终于卷土重来,血色十字军组织了一支先锋军前往诺森德大陆对抗天灾军团,以及一切沾有亡灵气息的生物。孤立于联盟和部落的血色先锋军很快就遭到了天灾军团的重重包围,现在他们将主力只好聚集了起来,以抵…...
systemd 与 SysVinit
1. 什么是 systemd 和 SysVinit? systemd 和 SysVinit 都是 Linux 的初始化系统(init system),用于管理系统启动、服务、进程和日志。 比较项SysVinitsystemd启动方式逐步启动(串行)并行启动(…...
PythonWeb项目-Django+vue白酒数据推荐系统功能介绍
❥(^_-) 上千个精美定制模板,各类成品Java、Python、PHP、Android毕设项目,欢迎咨询。 ❥(^_-) 程序开发、技术解答、代码讲解、文档,💖文末获取源码+数据库+文档💖 💖软件下载 | 实战案例 💖文章底部二维码,可以联系获取软件下载链接,及项目演示视频。 本项目源…...
AWS Bedrock:开启企业级生成式AI的钥匙【深度解析】
引言:生成式AI的工业革命需要新基建 根据Gartner预测,到2026年超过80%的企业将在生产环境中部署生成式AI。而AWS Bedrock作为首个企业级生成式AI托管平台,正在重塑AI工业化落地的技术范式。本文将深入解构其技术架构与商业价值。 一、Bedroc…...
网络安全应急响应-文件痕迹排查
在Windows系统的网络安全应急响应中,文件痕迹排查是识别攻击行为的关键步骤。以下是针对敏感目录的详细排查指南及扩展建议: 1. 临时目录排查(Temp/Tmp) 路径示例: C:\Windows\TempC:\Users\<用户名>\AppData\L…...
【玩转全栈】—— Django 连接 vue3 保姆级教程,前后端分离式项目2025年4月最新!!!
本文基于之前的一个旅游网站,实现 Django 连接 vue3,使 vue3 能携带 CSRF Token 发送 axios 请求给后端,后端再响应数据给前端。想要源码直接滑倒底部。 目录 实现效果 解决跨域 获取 csrf-token 什么是 csrf-token ? CSRF攻击的…...
网络安全·第一天·IP协议安全分析
本篇博客讲述的是网络安全中一些协议缺陷以及相应的理论知识,本博主尽可能讲明白其中的一些原理以及对应的防卫措施。 学习考研408的同学也能进来看看,或许对考研有些许帮助(按照考研现在的趋势,年年都有新题目,本文当…...
TensorFlow深度学习实战——字符嵌入、子词嵌入、句子嵌入和段落嵌入
TensorFlow深度学习实战——字符嵌入、子词嵌入、句子嵌入和段落嵌入 0. 前言1. 字符嵌入2. 字词嵌入3. 句子嵌入和段落嵌入相关链接 0. 前言 在自然语言处理中,嵌入 (Embedding) 技术是将文本转化为数值向量的核心方法,使计算机能够理解和处理语言中的…...
剖析AI与5G:是夸大其词,还是时代变革的引擎?-优雅草卓伊凡
剖析AI与5G:是夸大其词,还是时代变革的引擎?-优雅草卓伊凡 在当今科技飞速发展的时代,AI与5G无疑是两大备受瞩目的焦点。近日,一个引人深思的问题浮出水面:“AI是不是被夸大了,就像当年的5G一样…...