Lua 的 # 获取长度

使用# 来夺取table长度时需要注意

tableTest = {1,2,7,9,10}
print(#tableTest) ---------------> 5   (这种会自动补上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为非数字,那么#tb获取到的长度也是0。

所以在确保table中的键值是从1,2开始连续向后,而且没有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的长度返回。二分查找的条件就是序列是有序,要不查的结果也不可信(像在一堆整数里查看是否有某个值,如果使用二分查找的话,前提就要先排序,然后查找,不先排序的话,找的结果不可信)。序也就是前提条件,这里取table的长度的前提条件就是,从键1到n(n为当前表非负整数key中最大值)所有键对应的值都不为nil ,否则二分查找的前提条件不满足,取长度的结果就不可信。

注意:如果表中还有非整数key-value,#取的结果只是整数部分长度。还有如表tt={1,2,3} tt[1000]=8; tt[2]=nil 后面再进行取长度操作也是不可信的。

适用情况:像我之前项目中一些临时表,初化元素时没有指定key(默认从1开始),如tt={100,200,300,{1,2},"hello world"} ,后面添加用table.insert,没有删除和其他添加元素方式,这种情况使用#取长度就没什么问题。

还可以采用下面的封装方法,获取table的元素个数。注意,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#中字符串默认的使用utf-16编码,理论上和unicode编码对应,使用两字节存储一个字符,不管什么字符都是用2个字节存储。

lua呢,lua文件一般读取的时候就采用utf-8编码,字符串也采用utf-8来存储的。utf-8是可变的编码格式。下面就来说一下,utf-8是如何存储的。

相信大家知道unicode字符集吧,包含了全世界的字符,然而它只是规定了字符的二进制编码,并没有规定二级制编码是如何存储的。utf-8就是unicode的一个实现方式,就是怎么存储和读取这个unicode二进制编码。

utf-8是一个可变长的编码方式,有的是用1个字节存,有的采用2个,有的3个,最多可采用6个字节,既然是可变的,就要求字节中有个位数用来表示标记的,,有了标记就知道怎么读取字节了。

1个字节表示的编码,最高位是0,像这样0xxxxxxx,后面7位x,用来表示unicode编码,当然7位表示的编码有限,

不是1个字节的编码,而就是n个字节的编码,就需要第一个字节的前n位用1表示,n+1位用0,其余的字节,前两位是10,如2个字节的 110xxxxx 10xxxxxx,3个字节的1110xxxx 10xxxxxx 10xxxxxx等的,除了符号位,剩下的x就用来表示unicode编码了,例如 "严"的unicode是4E25,二进制是100111000100101,需要16位,能表示16位的utf-8,就需要3个字节了。

总之,在lua中,通过string.len获取的字符串的字节长度,采用utf-8存储的。

在网上下载一份,获取lua字符长度的方法

-- 获取字符串的长度(任何单个字符长度都为1)
function getStringLength(inputstr)
    if not inputstr or type(inputstr) ~= "string" or #inputstr <= 0 then
        return nil
    end
    local length = 0  -- 字符的个数
    local i = 1
    while true do
        local curByte = string.byte(inputstr, i)--根据首字节的大小确定
        local byteCount = 1
        if curByte > 239 then --11110xxx
            byteCount = 4  -- 4字节字符
        elseif curByte > 223 then --1110xxxx
            byteCount = 3  -- 3字节字符
        elseif curByte > 128 then  --110xxxxx
            byteCount = 2  -- 双字节字符
        else
            byteCount = 1  -- 单字节字符
        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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容