要求:
input will only contain the characters a-z
Example:
"aaabbac" -> "a3b2ac" "aaaaa" -> "a5" "" -> ""
我的方法是:
def zip_code(s)
return "包含不合要求字符串" if s =~ /[^a-z]/
('a'..'z').each {|c| s.scan(/#{c}{2,}/).sort_by{|e| e.size}.reverse.each{|cha| s.gsub!(cha, "#{c}#{cha.size}") } }
s
end
每次这样处理压缩文本字符,然后用的时候再解析出来,这种功能自己做有点吃力而且很难做好吧; 原始需求是什么
最最早文本存储为了压缩空间是自定义文件格式/存储格式,前多少是字符格式,中间几位是二进制,后面什么格式;然后数据定长变长的;这种 ruby 原生没这套东西。
另外我记得有直接处理 zip 文件的。
正则替换的解法:
"aaabbac".gsub(/(([a-z])\2*)/) {|s| $1.length > 1 ? $2 + $1.length.to_s : $2}
#11 (?<=exp) 猛然想到曾经用过 叫叫... 零宽断言?这个概念字面让人很不懂 晦涩 #7 \1 \2是什么意思 \1匹配第一个 () 里面的内容 \2匹配第二个 () 的内容么
'a'..'z' , '1'..'9' , 35 个字符 35.to_s(2) => "100011" 6 位
8 位的数据用 6 位存放,可以再压缩 75%
11 楼 @luikore
对师父的正则进行改写。不用断言,似乎更清晰一些。 $1 是第一个匹配,$& 是所有匹配。
'aaabbac'.gsub(/([a-z])(\1+)/) { $1+$&.size.to_s }
一部分灵感,来自于当年 @hooopo 的经典回帖. http://ruby-china.org/topics/2504 五楼。
叫做 "往后看" (左边是后右边是前)
师父的解释,是基于:默认正则的 back track 特性而言的吧?和直觉上正好相反,我编辑器针对这个设定了快捷键,用的是:<, 有前的含义,称作 前置断言
是不是更形象一些?
我这个前是相对于被修饰的 (匹配的) 那个字符串而言的。
(?<=aaa)bbb, 这个 (?<=aaa) 是对 bbb 的前置断言。
我是这样理解的,这里的 (?<=aaa) 是用来验证 bbb 前面
有什么东西,所以自然而言联想出来这个叫法。