我有一个相当普遍的问题,我道歉它很冗长。它不仅与MySQL有关,而且可以用任何脚本语言完成,但我找不到更好的解释方法。我有一个独特的单词列表。现在他们在MySQL的表中,但实现并不重要,它们也可以在文本文件中。每个单词都是6个字符。单词遵循几种略有不同的格式。我的目标是将每个单词从6个字符缩短为4个字符,保留唯一性。
我搜索了主题,所有数据最小化/优化/碰撞都没有提供有用的结果:(所以我在这里。
以下是一个示例:
--------------
words
--------------
word short
------ ----
1A0001
1A0002
1A0003
AA0001
AA1001
AB0001
2BAC11
2BAC34
--------------
正如您所看到的,有三种格式可以用以下通用正则表达式表示:
^[0-9][A-Z][0-9][0-9][0-9][0-9]$ - matches 1A0001 1A0002 1A0003
^[A-Z][A-Z][0-9][0-9][0-9][0-9]$ - matches AA0001 AA1001 AB0001
^[0-9][A-Z][A-Z][A-Z][0-9][0-9]$ - matches 2BAC11 2BAC34
因此,根据格式,可以删除不同的字符,使单词4个字符长,并使它们保持唯一。
^[0-9][A-Z][0-9][0-9][0-9][0-9]$ - drop 1, 3
^[A-Z][A-Z][0-9][0-9][0-9][0-9]$ - drop 3, 4
^[0-9][A-Z][A-Z][A-Z][0-9][0-9]$ - drop 1, 4
我使用short
创建regexp/concat/substring
的值,并使用临时表对words
进行更新。正如我所说,实施对解释并不重要。它几乎归结为:
select concat(substring(word,2,1), substring(word,4,3)) from words where word regexp '^[0-9][A-Z][0-9][0-9][0-9][0-9]$';
select concat(substring(word,1,3), substring(word,6,1)) from words where word regexp '^[A-Z][A-Z][0-9][0-9][0-9][0-9]$';
select concat(substring(word,2,2), substring(word,5,2)) from words where word regexp '^[0-9][A-Z][A-Z][A-Z][0-9][0-9]$';
这就是表格最终的样子:
--------------
words
--------------
word short
------ ----
1A0001 A001
1A0002 A002
1A0003 A003
AA0001 AA01
AA1001 AA11
AB0001 AB01
2BAC11 BA11
2BAC34 BA34
--------------
我可以使用以下方式验证short
的唯一性:
mysql> select short from words group by short having count(short) > 1;
Empty set (0.00 sec)
mysql>
这是非常简化的方案。实际上,单词更长,格式更多。有时即使格式相同,删除相同的字符也会产生冲突,这意味着两个不同的word
会导致相同的short
,这是不可接受的。因此需要修改short
以使其成为唯一的。最大的困难来自于所有word
实际上都是人类可理解的事实,因此short
版本应该是人类可理解的并且与原始word
相似。这意味着我无法创建某种散列算法来确保短版本的唯一性,这还不够,它必须有点像原始单词。现在我正在考虑用0
替换O
,依此类推。
我猜你觉得这更像是一个科学问题,而不是一个实施问题。实施的唯一重要方面是性能。我希望有一个好的表现,所以我不必永远等待。
有人见过类似的东西吗?
我会从哪里开始寻找方法呢?