Backstory
I'm working on a small interactive piece and need a way to uniquely keep track of object names using only integers. I thought I had a solution but once I fix a collision I seem to get into another.
example of object names:
/=====Folders=====/MAZE/Grid Spawner/Cell ((0, 0))/Room (0, 0)/Level 0, Drawer/drawer_0
where all the 0
values can be anything from 1-10
Question
How can I make sure that any entry I come across can turn into a unique integer?
Code
let arr = [
"/=====Folders=====/MAZE/Grid Spawner/Cell ((0, 0))/Room (0, 0)/Level 0, Drawer/drawer_1",
"/=====Folders=====/MAZE/Grid Spawner/Cell ((0, 1))/Room (0, 0)/Level 0, Drawer/drawer_1",
"/=====Folders=====/MAZE/Grid Spawner/Cell ((0, 2))/Room (0, 0)/Level 0, Drawer/drawer_2",
"/=====Folders=====/MAZE/Grid Spawner/Cell ((0, 0))/Room (0, 3)/Level 0, Drawer/drawer_1",
"/=====Folders=====/MAZE/Grid Spawner/Cell ((0, 0))/Room (0, 0)/Level 0, Drawer/drawer_3",
"/=====Folders=====/MAZE/Grid Spawner/Cell ((0, 3))/Room (0, 0)/Level 0, Drawer/drawer_2"];
function GameObjectPathToInt(str) {
let ret = 0;
for(let i = 0; i < str.length; i)
{
let posVal = 1 i;
let charVal = 1 str.charCodeAt(i);
ret = posVal * charVal;
/* console.log(charVal, str[i]) */
}
return ret;
}
arr = arr.map((str) => GameObjectPathToInt(str));
/* console.log(arr.sort()); */
arr.reduce((prev, cur) => {prev == cur ? console.log("DUPLICATE", cur) : null; return cur});
body {
background-color: black;
}
CodePudding user response:
Assuming those numbers in the string are what makes it unique, why not extract that info from the string?
const GameObjectPathToInt = (string) => {
var matches = string.matchAll(/\d /g);
return parseInt("1" [...matches].join("")) // 1 prevents leading 0 being stripped
}
Likely the reason your original plan doesn't work is the number could be equivalent if you swap some characters around. You attempt to handle it I think but still whilst i
increases, charCode
could decrease and end up clashing.
You might be able to get it working by concatenating a number as a string then converting it like above. That way you make it order-derived.
You could also consider using SHA1 and then converting the resulting hexadecimal to a number.
CodePudding user response:
If strict uniqueness and inversion is not needed, maybe utilizing an existing hashing algorithm is a better choice than inventing something new.
If not, then a simple way may be constructing a BigInt
with each 16 bits representing an character (suitable with only BMP characters; if characters like emojis exist in paths, consider giving 21 bits for each character or using surrogate pairs):
let str = "/=====Folders=====/MAZE/Grid Spawner/Cell ((0, 0))/Room (0, 0)/Level 0, Drawer/drawer_1";
let id = 0n;
for (let ch of str) {
id <<= 16n;
id |= BigInt(ch.charCodeAt(0)); // will only get the first surrogate for special chars
}
console.log(id.toString());