【问题标题】:Shortening a string in Java在Java中缩短字符串
【发布时间】:2011-06-09 21:32:30
【问题描述】:

我需要将像“ABC123”这样的 6 个字符的字符串缩短为一个唯一的 4 个字符的字符串。它必须是可重复的,以便输入字符串始终生成相同的输出字符串。有没有人对如何做到这一点有任何理想?

【问题讨论】:

  • 我不明白你的要求。您想要从 6 个字符串到 4 个字符串的唯一映射吗?这不可能是 1-1,因为您映射的对象是您映射对象的子集..

标签: java


【解决方案1】:

不可能进行从 6 个字符的字符串到 4 个字符的字符串的完全唯一映射。这是一个简单的hash function 示例。因为范围空间小于域空间,所以你必然会有一些哈希collisions。您可以尝试根据您要接受的数据类型来最小化冲突的数量,但最终不可能将每个 6 个字符串映射到一个唯一的 4 个字符串,您将用完 4 个字符串。

【讨论】:

    【解决方案2】:

    你需要对输入字符串做一些限制,否则数学难免会咬你。

    例如,假设您知道它仅由大写字母和数字组成。因此,有 36^6 个可能的输入字符串。

    结果需要有更少的限制,例如您允许 216 个不同的字符(可打印的扩展 ascii 或类似的字符)。

    纯巧合,216^4 = 36^6,所以你需要的是一个映射。这很简单,只需使用将数字表示从一个基数转换为另一个基数的算法即可。

    【讨论】:

      【解决方案3】:

      不确定是否可以这样做,因为我敢打赌会有一些业务限制(比如用户必须能够输入密钥)。

      这个想法是将值“散列”到较少的位置。这需要一个足够大的字符集来处理所有组合。

      假设原始键不区分大小写,您有 26 + 10 = 32,然后提升到第 6 个唯一组合(2,176,782,336 个唯一组合)。要仅在 4 个字符中匹配,您必须使用具有 216 个唯一字符的字符集,因为 216 ^ 6 是 2,176,782,336 或第一个数字提高到 4 的组合比不区分大小写的键与数字的组合更多。 (不区分大小写,加上数字只带你到 62)。

      如果我们使用标准美式键盘,我们有 26 个字母 x 2 个大小写 = 52 10 个号码 数字键上的 10 个特殊字符 其他 11 个特殊字符键 * 2 = 22

      这是 94 个唯一字符,或者不到将不区分大小写的 6 位数代码转换为 4 位数所需的唯一字符的一半。现在,在克林贡星球上,键盘要大得多... ;-)

      如果密钥不区分大小写,则您的字符集必须扩展为 489 个唯一字符以适应 4 位“哈希”。哎哟!

      【讨论】:

        【解决方案4】:

        假设:输入字符串只能包含 ASCII 十进制值低于 128 的字符...否则,正如其他人所说,这将不起作用。

        public class Foo {
        
            public static int crunch(String str) {
                int y = 0;
                int limit = str.length() > 6 ? 6 : str.length();
                for (int i = 0; i < limit; ++i) {
                    y += str.charAt(i) * (limit - i);
                }
                return y;
            }
        
            public static void main(String[] args) {
                String[] words = new String[]{
                    "abcdef", "acdefb", "fedcba", "}}}}}}", "ZZZZZZ", "123", "!"
                };
        
                for (int idx = 0; idx < words.length; ++idx) {
                    System.out.printf("in=%-6s out=%04d\n",
                      words[idx], crunch(words[idx]));
                }
            }
        }
        

        生成:

        in=abcdef out=2072
        in=acdefb out=2082
        in=fedcba out=2107
        in=}}}}}} out=2625
        in=ZZZZZZ out=1890
        in=   123 out=0298
        in=     ! out=0033
        

        【讨论】:

          【解决方案5】:

          您必须对字符可以具有的值范围以及何时是可接受的编码字符做出假设。有多种方法可以做到这一点。根据您的假设,您可以将字符串打包为 1、2、3、4 或 5 个字符。

          一个简单的例子就是假设最后三个字母是一个数字。

          public static String pack(String text) {
              return text.substring(0, 3) + (char) Integer.parseInt(text.substring(3));
          }
          
          public static String unpack(String text) {
              return text.substring(0, 3) + ("" + (1000 + text.charAt(3))).substring(1);
          }
          
          public static void main(String[] args) throws IOException {
              String text = "ABC123";
              String packed = pack(text);
              System.out.println("packed length= " + packed.length());
              String unpacked = unpack(packed);
              System.out.println("unpacked= '" + unpacked + '\'');
          
          }
          

          打印

          packed length= 4
          unpacked= 'ABC123'
          

          【讨论】:

            猜你喜欢
            • 2011-11-15
            • 1970-01-01
            • 2017-11-11
            • 2011-04-28
            • 2019-10-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-04-23
            相关资源
            最近更新 更多