如何用GDScript将整数数组高效压缩为可还原的紧凑字符串?
整数数组压缩需求与优化方案
目标
将类似[12, 1, -34, 55, 13, 341, 11, 56, 321, -3422, 1222, -4, 237]的整数数组压缩为更小尺寸的可还原字符串。
原因
过长的字符串会导致使用的数据库管理器交互时冻结(数组以字符串格式存储)。
背景
实际存储的是网格坐标列表,例如[Vector3(1,2,3), Vector3(4,5,6)]会转换为[1,2,3,4,5,6],基于GDScript开发。
现有尝试
针对上述示例数组,我实现的最优压缩结果为:"c1-y.Td,y1.bU,w1-ym,cm-4,n7"
实现逻辑:将大于9的数值对映射为非数字字符(如10=a,11=b,61=Z),仅在多字符转换结果间使用逗号,同时把"-"用作类逗号符号(逻辑较复杂)。经200组随机数组测试,平均减容48%(不含空白字符)。
问题
是否有更优的方法实现该需求?
补充:个人GDScript实现方案
以下是我编写的GDScript代码,供参考:
extends Node var negative_character_index = 50000 # 跳过空白字符以及"."、","、"()",这些用于特殊场景 var start_char = 47 func num_to_char(num: int): var x = abs(num) if x > negative_character_index: # 数值过大,无法转换 return else: x += start_char if num < 0: x += negative_character_index var char = String.chr(x) return char func char_to_num(char : String): var x = char.unicode_at(0) - start_char if x == null: # 可能negative_character_index被修改 breakpoint if x > negative_character_index: x -= negative_character_index x *= -1 return x # 压缩单个整数 func int_to_compact_int_string(n:int): var compact_n = "" # 记录当前可转换的最长前缀 var head = "" var last_head_int = null var last_char = null var get_zeros_code = func(head): var zeros = 0 if head.begins_with("0"): for char2 in head: if char2 == "0": zeros += 1 else: break if head.right(1) == "0": zeros -=1 if zeros > 0: return "("+str(zeros)+")" return "" for num in str(n): head += num print(head) if num != "-": var head_int = str_to_var(head) var char = get_zeros_code.call(head) + num_to_char(head_int) print(char) if last_head_int != null && char == null: compact_n += last_char head = "" head += num last_head_int = str_to_var(head) last_char = get_zeros_code.call(head) + num_to_char(last_head_int) else: last_head_int = head_int last_char = char print("~~~") if head != "": print(head) print(last_char) print("~~~") compact_n += last_char return compact_n # 将整数数组压缩为字符串 func int_arr_to_compact_str(int_arr): var compact_str = "" var is_multi = false for n in int_arr: var compact_n:String = int_to_compact_int_string(n) if compact_n.length() > 1: # 多字符压缩结果用逗号分隔 compact_str += "," is_multi = true elif is_multi: compact_str += "." is_multi = false compact_str += compact_n return compact_str # 还原单个压缩后的整数 func new_compact_int_string_to_int(compact_n:String): var n = "" var is_zeros = false var zeros = "" for char in compact_n: if char == "(": is_zeros = true zeros = "" elif char == ")": is_zeros = false var i = 0 while i < str_to_var(zeros): n += "0" i+=1 elif is_zeros: zeros += char else: var index = char_to_num(char) if index > negative_character_index: index -= negative_character_index index *= -1 n += str(index) return str_to_var(n) # 将压缩字符串还原为整数数组 func new_compact_str_to_int_arr(compact_str): var int_arr = [] var is_multi = false var multi_compiler = "" for char in compact_str: if char == ',' || char == '.': is_multi = char == ',' # 结束当前多字符数值的编译 if multi_compiler.length() >0: int_arr.append(new_compact_int_string_to_int(multi_compiler)) multi_compiler = "" else: if is_multi: multi_compiler += char else: int_arr.append(new_compact_int_string_to_int(char)) if multi_compiler.length() > 0: int_arr.append(new_compact_int_string_to_int(multi_compiler)) multi_compiler = "" return int_arr func _ready(): var arr2 = [237, 50001, -5000000003, 250000000] # print("---") # for i in range(999): # print(String.chr(i)+" -> "+str(i)) # print("---") print(arr2) var comp = int_arr_to_compact_str(arr2) print(comp) var r_arr2 = new_compact_str_to_int_arr(comp) print(r_arr2)
内容的提问来源于stack exchange,提问作者DED
相关产品推荐
相关产品推荐

