Есть ли способ взять уникальную строку из 256 символов, уменьшить ее размер с помощью JS до уникальной строки из 50 ± символов и сохранить гарантированную уникальность? - PullRequest
0 голосов
/ 02 ноября 2019

Я работаю над созданием синтаксического анализатора для текстового файла для встраивания в объект JSON.

Предполагается, что где-то в строке есть строка с уникальным значением: 4E183437F3FAEBC107C333CD16657661598A2A523867A4A95F6DAD4D25E191722AFFB3FFE29E287D9EB21ED8035E7666D06E65EC064D5D4B337C034459BA7CD6F72437B439329B45F15D57176122965728B36DBB455D335AA904106A29B64694507B6A0F89FBF4A166BB3BBB4DDDC1674A1DB3B7D0FD332117877C4CE56465D8

Я хочу использовать этот уникальный идентификатор как key на каком-то уровне, но это слишком долго, чтобы соответствовать моим вкусам.

Мне интересно, есть ли способ создать меньший хэш:

  1. но не теряется и информация
  2. гарантирует уникальность
  3. и будет преобразована обратно в исходную

Некоторая библиотека / плагин?

1 Ответ

0 голосов
/ 02 ноября 2019

Вы можете создать строку меньшей длины, превратив 16-битную шестнадцатеричную строку в число (с BigInt), а затем создав новую строку с основанием, скажем, 10000, чтобысимвол с кодом символа C представляет число 'C'.charCodeAt().

Затем верните его обратно в исходную строку, выполнив тот же процесс в обратном порядке.

Длина строки короче, и высохранено некоторых битов, но оно все еще длинное:

const encode = (input) => {
  let n = 0n;
  [...input].forEach((char, i) => {
    const code = char.charCodeAt();
    const value = BigInt(code <= 57 ? code - 48 : code - 55);
    n += value * (16n ** BigInt(i));
  });
  const base10Str = String(n);
  let output = '';
  for (let i = 0; i < base10Str.length; i += 4) {
    output += String.fromCharCode(base10Str.slice(i, i + 4));
  }
  return output;
};

const decode = (encoded) => {
  let base10Str = '';
  [...encoded].forEach((char) => {
    base10Str += String(char.charCodeAt()).padStart(4, '0'); // todo: final char may need no padding
  });
  let n = BigInt(base10Str);
  let inputStr = '';
  for (let i = 255; i >= 0; i--) {
    const thisHexMult = 16n ** BigInt(i);
    const thisHexDigitBigInt = n / thisHexMult; // This will automatically effectively call Math.floor
    n = n % thisHexMult;
    const thisHexDigit = Number(thisHexDigitBigInt);
    const charCode = thisHexDigit <= 9 ? thisHexDigit + 48 : thisHexDigit + 55;
    inputStr = String.fromCharCode(charCode) + inputStr;
  }
  console.log(inputStr);
};

const encoded = encode('4E183437F3FAEBC107C333CD16657661598A2A523867A4A95F6DAD4D25E191722AFFB3FFE29E287D9EB21ED8035E7666D06E65EC064D5D4B337C034459BA7CD6F72437B439329B45F15D57176122965728B36DBB455D335AA904106A29B64694507B6A0F89FBF4A166BB3BBB4DDDC1674A1DB3B7D0FD332117877C4CE56465D8');

console.log('Encoded length:', encoded.length);
console.log(encoded);

decode(encoded);
...