Есть несколько вещей, которые вы можете сделать. Вы можете вычесть 1 из каждой цифры и проанализировать ее как восьмеричное число, которое сопоставит однозначное число каждого вашего домена с диапазоном [0,16777216) без пробелов. Полученное число можно использовать как индекс в очень большом массиве. Пример этого может работать следующим образом:
function hash(num) {
return parseInt(num
.toString()
.split('')
.map(x => x - 1), 8);
}
const set = new Array(8**8);
set[hash(12345678)] = true;
// 12345678 is in the set
Или, если вы хотите сэкономить место и расширить структуру данных при добавлении элементов. Вы можете использовать древовидную структуру с 8 ветвями на каждом узле и максимальной глубиной 8. Я оставлю это на ваше усмотрение, чтобы выяснить, считаете ли вы, что это того стоит.
Редактировать :
После просмотра обновленного вопроса я начал думать о том, как можно сопоставить число с его положением в лексикографически отсортированном списке перестановок цифр 1-8. Это было бы оптимальным, потому что дает теоретический 5-значный хеш, который вы хотите (до 40320). У меня были некоторые проблемы с формулировкой алгоритма, чтобы сделать это самостоятельно, поэтому я немного покопался. Я нашел пример реализации , который делает именно то, что вы ищете. Я черпал вдохновение для реализации этого алгоритма на JavaScript для вас.
function hash(num) {
const digits = num
.toString()
.split('')
.map(x => x - 1);
const len = digits.length;
const seen = new Array(len);
let rank = 0;
for(let i = 0; i < len; i++) {
seen[digits[i]] = true;
rank += numsBelowUnseen(digits[i], seen) * fact(len - i - 1);
}
return rank;
}
// count unseen digits less than n
function numsBelowUnseen(n, seen) {
let count = 0;
for(let i = 0; i < n; i++) {
if(!seen[i]) count++;
}
return count;
}
// factorial fuction
function fact(x) {
return x <= 0 ? 1 : x * fact(x - 1);
}