如何将字符串位数格式化为偶数

一个字段存在奇数位和偶数位,想统一成偶数位,在奇数位前加0,执行下面这个语句,select Code, iif(Code.strlen() % 2 = 0, Code, `0 + Code) from tmpCode,30M的表执行起来竟然耗费了5G内存,执行速度也很慢,有什么更轻便快捷的方法吗?

请先 登录 后评论

2 个回答

Polly

可以借助 lpad 进行填充:

def evenLPad(str, pad): lpad{,,pad}:E(str, 2*ceil strlen(str)\2)

如果要提升运行效率,可以用:

def evenLPad(str, pad): lpad{,,pad}:E(str, 254&strlen(str)+1)

在字符串多的场景下,可以提升 20 % 左右的性能

请先 登录 后评论
SaintM

模拟生成200万行的内存表 tb,tb 中的code字段下是字面量为“1”,“2”,“3”到“2000000”的字符串的值。

n = 2000000
tb = table(string(1..n) as code)

attachments-2024-01-8Y39nhd365b3865cbf7c9.png

可以通过以下两种思路来解决问题:

使用 iif 语句选择性补零。

tb.update!(`paddedCode, iif(tb.code.strlen() % 2 == 0, tb.code, `0 + tb.code))

使用lpad 左填充函数,对奇数长度的字符串补零。

如下,在自定义函数 evenZeroPad 中,对传入的字符串计算出最接近且不小于字符串长度的偶数,并根据该数调用lpad 内置函数进行补零。之后再使用 each 高阶函数,使得 evenZeroPad 函数可以对 tb 的 code字段进行逐行调用。

def evenZeroPad(x): lpad(x, 2*ceil strlen(x)\2, `0)
tb.update!(`paddedCode, evenZeroPad:E(tb.code))

统一补零后使用 substr 函数截取字符串。

如下,先对code字段的值统一补零,然后在自定义函数 evenZeroPad 中,对传入的字符串调用 substr内置函数做截取。补一位零之后长度为奇数的字符串要从第二位开始截取(offset=1),补一位零之后长度为偶数的字符串从第一位开始截取(offset=0)。

def evenZeroPad(x): substr(x, strlen(x) & 1)
tb.update!(`paddedCode, evenZeroPad:E(`0 + tb.code))

性能测试

数据量:200W行 1列,大小约 45.8 MB

耗时:timer函数统计的单次执行的耗时

内存占用:执行前后,通过 top 指令查看到的dolphindb内存占用的差值

  1. 方案一, 耗时(s):0.08, 内存占用(MB):100.96
  2. 方案二,耗时(s):2.13, 内存占用(MB):183.02
  3. 方案三,耗时(s):1.34内存占用(MB):274.66


请先 登录 后评论