使用# 來奪取table長度時需要注意
tableTest = {1,2,7,9,10}
print(#tableTest) ---------------> 5 (這種會自動補(bǔ)上key值)
tableTest1 = {1,2,nil,3,5,7}
print(#tableTest) ---------------> 6
tableTest2= {1,nil,2,nil,3,nil}
print(#tableTest) ---------------> 3
可以看到如果其中元素有nil值的話,#方法是完全失效了
local tab = {}
tab["1"] = 1
tab["2"] = 1
tab["3"] = 1
print(#tab) ----------> 0
如果table的第一個元素key為非數(shù)字趾痘,那么#tb獲取到的長度也是0。
所以在確保table中的鍵值是從1卵贱,2開始連續(xù)向后,而且沒有nil元素的情況下才可以使用
(如果是從0開始键俱,會忽略0)
int luaH_getn (Table *t) {
unsigned int j = t->sizearray;
if (j > 0 && ttisnil(&t->array[j - 1])) {
/* there is a boundary in the array part: (binary) search for it */
unsigned int i = 0;
while (j - i > 1) {
unsigned int m = (i+j)/2;
if (ttisnil(&t->array[m - 1])) j = m;
else i = m;
}
return i;
}
/* else must find a boundary in hash part */
else if (t->node == dummynode) /* hash part is empty? */
return j; /* that is easy... */
else return unbound_search(t, j);
}
這個是lua5.1中求table長度的方法,是二分查找的思路世分。用二分法找到一個索引i,使得t[i]存在而t[i+1]為nil,就把i作為table的長度返回臭埋。二分查找的條件就是序列是有序,要不查的結(jié)果也不可信(像在一堆整數(shù)里查看是否有某個值畅蹂,如果使用二分查找的話,前提就要先排序魁莉,然后查找,不先排序的話旗唁,找的結(jié)果不可信)痹束。序也就是前提條件,這里取table的長度的前提條件就是祷嘶,從鍵1到n(n為當(dāng)前表非負(fù)整數(shù)key中最大值)所有鍵對應(yīng)的值都不為nil 夺溢,否則二分查找的前提條件不滿足烛谊,取長度的結(jié)果就不可信。
注意:如果表中還有非整數(shù)key-value丹禀,#取的結(jié)果只是整數(shù)部分長度。還有如表tt={1,2,3} tt[1000]=8; tt[2]=nil 后面再進(jìn)行取長度操作也是不可信的持搜。
適用情況:像我之前項目中一些臨時表,初化元素時沒有指定key(默認(rèn)從1開始)葫盼,如tt={100,200,300,{1,2},"hello world"} ,后面添加用table.insert贫导,沒有刪除和其他添加元素方式蟆盹,這種情況使用#取長度就沒什么問題。
還可以采用下面的封裝方法日缨,獲取table的元素個數(shù)。注意匣距,pairs 記錄的是非nil的元素。
function table.length()
local count = 0
for k,v in paris(table1) do
count = count +1
end
return count
end
獲取字符串長度
對于字符串來說尚卫,#是獲取字符串長度
local str = "abc"
local len = #str
print(len) -- 3
str = "你們好"
len = #str
print(len) -- 9
c#中字符串默認(rèn)的使用utf-16編碼,理論上和unicode編碼對應(yīng)吱涉,使用兩字節(jié)存儲一個字符,不管什么字符都是用2個字節(jié)存儲怎爵。
lua呢盅蝗,lua文件一般讀取的時候就采用utf-8編碼,字符串也采用utf-8來存儲的墩莫。utf-8是可變的編碼格式逞敷。下面就來說一下灌侣,utf-8是如何存儲的。
相信大家知道unicode字符集吧侧啼,包含了全世界的字符,然而它只是規(guī)定了字符的二進(jìn)制編碼慨菱,并沒有規(guī)定二級制編碼是如何存儲的戴甩。utf-8就是unicode的一個實(shí)現(xiàn)方式,就是怎么存儲和讀取這個unicode二進(jìn)制編碼甜孤。
utf-8是一個可變長的編碼方式,有的是用1個字節(jié)存缴川,有的采用2個,有的3個而线,最多可采用6個字節(jié),既然是可變的膀篮,就要求字節(jié)中有個位數(shù)用來表示標(biāo)記的,誓竿,有了標(biāo)記就知道怎么讀取字節(jié)了谈截。
1個字節(jié)表示的編碼,最高位是0簸喂,像這樣0xxxxxxx,后面7位x喻鳄,用來表示unicode編碼,當(dāng)然7位表示的編碼有限诽表,
不是1個字節(jié)的編碼隅肥,而就是n個字節(jié)的編碼袄简,就需要第一個字節(jié)的前n位用1表示,n+1位用0绿语,其余的字節(jié),前兩位是10吕粹,如2個字節(jié)的 110xxxxx 10xxxxxx,3個字節(jié)的1110xxxx 10xxxxxx 10xxxxxx等的匹耕,除了符號位,剩下的x就用來表示unicode編碼了稳其,例如 "嚴(yán)"的unicode是4E25,二進(jìn)制是100111000100101煤傍,需要16位,能表示16位的utf-8蚯姆,就需要3個字節(jié)了洒敏。
總之,在lua中桐玻,通過string.len獲取的字符串的字節(jié)長度,采用utf-8存儲的镊靴。
在網(wǎng)上下載一份,獲取lua字符長度的方法
-- 獲取字符串的長度(任何單個字符長度都為1)
function getStringLength(inputstr)
if not inputstr or type(inputstr) ~= "string" or #inputstr <= 0 then
return nil
end
local length = 0 -- 字符的個數(shù)
local i = 1
while true do
local curByte = string.byte(inputstr, i)--根據(jù)首字節(jié)的大小確定
local byteCount = 1
if curByte > 239 then --11110xxx
byteCount = 4 -- 4字節(jié)字符
elseif curByte > 223 then --1110xxxx
byteCount = 3 -- 3字節(jié)字符
elseif curByte > 128 then --110xxxxx
byteCount = 2 -- 雙字節(jié)字符
else
byteCount = 1 -- 單字節(jié)字符
end
-- local char = string.sub(inputstr, i, i + byteCount - 1)
-- print(char) -- 打印單個字符
i = i + byteCount
length = length + 1
if i > #inputstr then
break
end
end
return length
end
參考:
https://iteacher.blog.csdn.net/article/details/89374675?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link
https://zhuanlan.zhihu.com/p/374527152