3.9 字符串

Ruby Javascript Go Lua
存储 1.8 字节序列
1.9 字符序列
UCS-2 Unicode 8位字节
可变性 可变
str[-1]='hi'
不可变 不可变 不可变
字面量 单引号, 双引号
单双有别, 双引号支持模板
单引号, 双引号 双引号:支持转义
反引号:不支持转义
单引号, 双引号
长度 字节: bytesize
字符:length size
字符: length属性 字节: len(str)
字符: len([]rune(str))
字符: #
遍历 字节: each_byte
字符:each_char
字符码:each_codepoint
行遍历:each_line
字符: for i
ES6: for of
字节: for i
字符: for range
for i = 1, #str do ... end
索引访问 str[i]
倒序索引: str[-1]
str[i] charAt[i]
ES6: at(i)
str[i] string.sub(str,start,end)
左闭右闭,索引从0开始,支持负数倒序
索引越界 nil undefined panic 空字符串
片段 str[start, len]
str(start..end)
substring(start,end)左闭右开
substr(start[,length])
切片语法: str[start:end] 左闭右开 string.sub(str,start,end)
拼接 str1+str2
模板字符串内插
String#<<
str1+str2
concat(str1,...)
str1 + str2 str1+str2
to 数组 split(pattern=nil, [limit]) split([separator[, limit]]) 字节: byte(str)
字符: []rune(str)
无内置实现
from 数组 Array#join(separator=$,) Array#join([separator]) string(byte_or_rune_array) table.concat (list [, sep [, i [, j]]])
字符串模板 支持 ES6支持 支持 无内置实现

1. Ruby

字符串可变

str[-1] = 'hi'
str[2, 5] = 'hello'
str[5, 6] = '' //相当于删除

每次遇到一个字符串字面量, 都会新建一个字符串对象

最佳实践: 减少在循环中使用字符串字面量

单双有别

字符串字面量同时支持单引号和双引号, 双引号支持模板字符串, 双引号不支持

最佳实践: 在不需要模板字符串的地方, 始终使用单引号

拼接

  • str + other_str → new_str: 不会自动转换类型, 要求操作数都是字符串(体现了Ruby的强类型), 返回新对象
  • 模板字符串内插: 会自动调用to_s, 不创建新对象, 效率更高
  • str << integer → str 数字将解释为码点
    str << obj → str 拼接前会自动转换右值
  • str * integer → new_str

最佳实践: 优先使用模板字符串


2. Javascript

ES6 对字符串进行了很多扩展.

字符串模板

`${start}, my name is ${getName()}, ${conf.fav} is my favourite`

遍历器接口

for (let char of '语言的学习') {
  console.log(char);
}

3. Go

string is the set of all strings of 8-bit bytes, conventionally but not necessarily representing UTF-8-encoded text. A string may be empty, but not nil. Values of string type are immutable.

字符串是一系列8位字节的集合,通常但不一定代表UTF-8编码的文本。字符串可以为空,但不能为nil。而且字符串的值是不能改变的, 定义大致如下:

type stringStruct struct {
  str unsafe.Pointer
  len int
}

其中str指向了一个byte数组.

  • 内建的len方法可以得到字符串的长度,每个字节可以根据索引得到,不能像 C 语言一样得到某个字节的地址,&s[i]这样做是非法的.

  • 加法拼接字符串, 每次需要重新分配内存, 在构建超大字符串时, 性能低下

    优化: 使用strings.Join(a []string, sep string) 会一次性计算并分配需要的内存

[]byte

byte是uint8, 定义如下

type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}

string和[]byte 的区别

  • string可以直接比较,而[]byte不可以,所以[]byte不可以当map的key值
  • 因为无法修改string中的某个字符,需要粒度小到操作一个字符时,用[]byte
  • string值不可为nil,所以如果你想要通过返回nil表达额外的含义,就用[]byte
  • []byte切片这么灵活,想要用切片的特性就用[]byte
  • 需要大量字符串处理的时候用[]byte,性能好很多

string和[]byte的相互转换:

  • 将string转为[]byte: []byte(string)
  • 将[]byte转为string: string([]byte)

4. Lua

单双有别

  • 单引号字符串不解释反斜杠转义序列
  • 双引号字符串解释反斜杠转义序列

Lua 标准库的吝啬, 在string的API上可见一斑, 很多其他语言操作字符串的API, 在lua中都没有原生的支持, 不过通常在lua社区都可以找到实现:


参考资料:

results matching ""

    No results matching ""