Home > Mobile >  generate unique Number from string
generate unique Number from string

Time:10-25

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());

  • Related