I want to know how to convert a one-dimensional array into a frequency dictionary with the elements of the array as keys, and their occurrences as values, in JavaScript.
For example, the following Python script creates a list of 1024 random numbers between 0 and 255 and counts the elements as described:
import random
from collections import Counter
sorted(Counter(random.randbytes(1024)).items(), key=lambda x: -x[1])
I can do the same in JavaScript, but much less concise:
var numbers = Array.from({length: 1024}, () => Math.floor(Math.random() * 256))
var counter = Object()
for (let number of numbers) {
if (counter.hasOwnProperty(number)) {counter[number] += 1}
else {counter[number] = 1}
}
Object.entries(counter).sort(([,a],[,b]) => b-a)
How do I make it more concise?
This surprised me: on my Mac, the Map version took 2.7s, and the Object version took 0.6s when testing with 100 million numbers.
(Your original version takes the same time as the Object version in the code below)
const numbers = Array.from({length:10**8},()=>Math.random()*256|0)
let timerStart = new Date()
{
let counter = new Map()
numbers.forEach(n=>counter.set(n,(counter.get(n)??0)+1))
counter = new Map([...counter].sort(([,a],[,b]) => b-a))
}
console.log(`Map version took ${new Date()-timerStart} ms`)
timerStart = new Date()
{
let counter = numbers.reduce((a,c)=>(a[c]=(a[c]??0)+1,a),{})
Object.entries(counter).sort(([,a],[,b]) => b-a)
}
console.log(`Object version took ${new Date()-timerStart} ms`)
Here's an ES6 one-liner to solve the problem, using Array.reduce and the fact that the value of a comma separated list of expressions is the value of the last one:
const numbers = Array.from({length: 1024}, () => Math.floor(Math.random() * 256))
const counter = numbers.reduce((acc, num) => (acc[num] = (acc[num] || 0) + 1, acc), {})
const sorted = Object.entries(counter).sort(([,a],[,b]) => b-a)
console.log(sorted)
You could try using a Map:
var numbers = Array.from({length: 1024}, () => Math.floor(Math.random() * 256))
const map = numbers.reduce((accum, d) => accum.set(d, (accum.get(d) || 0) + 1), new Map());
A quick "improvement" would be to use the ternary statement to make the code more concise.
var numbers = Array.from({length: 1024}, () => Math.floor(Math.random() * 256))
var counter = Object()
for (let number of numbers) {
//If counter has prop number, increment it by one otherwise set to 1
counter.hasOwnProperty(number) ? counter[number]++ : counter[number] = 1;
//Alternatively
//counter[number] = counter.hasOwnProperty(number) ? counter[number] + 1 : 1
}
Object.entries(counter).sort(([,a],[,b]) => b-a)
I am using React for my frontend app.
I have two different time format of data.
One is like this 08-10 and another one is like this 05:00-05:30.
Most of the time format data is like this 08-10, few are like 05:00-05:30.
After getting the time date data, I used map function and pass to my time-format helper function, In my browser I want to display my data like this 05:00-05:30.
My helper function do like this: if the time looks like this 08-10 then the function will split it into two then add : and convert them into 08:00-10:00. As I mentioned I have two different time format data, when the data come like this 05:00-05:30 then my helper function convert them like 0500-0530.
I want to render my function conditionally if the data is like 05:00-05:30 then return as it is, if the data is like this 08-10 then convert them into 08:00-10:00. I don't know how to do that in my helper function.
const toTimeRangeFormat = (range) => {
console.log(range);
const [start, end] = range?.split("-");
const toFourDigitTime = (time) => {
const [hours, minutes] = time.split(":");
return hours.padStart(2, "0") + (minutes ? minutes : ":00");
};
if (start && end) {
return toFourDigitTime(start) + " - " + toFourDigitTime(end);
}
return range;
};
const time = ["08-10", "05:00-05:30"];
time.filter((i) => {
if (typeof i === "string") {
return toTimeRangeFormat(i);
}
});
console.log(toTimeRangeFormat());
Your code seemed to work if you call it correctly
I assume you want this though
const re = /(\d{2}):?(\d{2})?/; // take the (set of) two digits from NN:NN, NNNN or NN - the ? means optional
const toFourDigitTime = time => {
const [hours, minutes] = time.match(re).slice(1); // ignore result[0]
return `${hours.padStart(2, "0")}:${minutes ? minutes : "00"}`;
};
const toTimeRangeFormat = (range) => {
const [start, end] = range ?.split("-");
if (start && end) {
return toFourDigitTime(start) + " - " + toFourDigitTime(end);
}
return range;
};
const time = ["08-10", "05:00-05:30"];
const time1 = time.map(str => toTimeRangeFormat(str));
console.log(time1);
How to get all possible variations of terms to add up to sum, in a given amount of piles, using javascript?
Let's say I have a sum of 10 and I want to split this into 4 piles with positive terms and zeros only.
function getCombinations(sum, piles){
...
}
getCombinations(10,4);
Returns something like this in a two dimensional array:
[
[3,3,3,1],
[3,3,1,3],
[7,1,1,1],
[10,0,0,0],
...
]
It's not mandatory to return [3,3,3,1] and [3,3,1,3] as different solutions, fastest way will do. I will only work with small numbers, max sum will probably be 10.
It's a variation of the Count the coins problem, http://rosettacode.org/wiki/Count_the_coins, but I want the solutions returned, I have a given set of piles and I use all positive terms (and zero) not only specific coin values.
this should do the trick:
const matrix = (num, cols) => {
const matrix = [[num, ...[...Array(cols-1)].map(() => 0)]];
const hashes = new Set;
const coef = Math.pow(10, cols-1);
let digits = 10 * coef - 1;
while (digits-- >= coef) {
const nums = ('' + digits).split('').map(d => +d);
const hash = nums.sort((a, b) => b - a).join('');
if (hashes.has(hash) || nums.reduce((a, b) => a + b, 0) !== num)
continue;
hashes.add(hash);
matrix.push(nums);
}
return matrix;
};
console.log(matrix(10, 4));
Here is a pratical way of doing this:
function getCombinations(sum, piles){
var array =[];
for(var i = 1; i <= piles; i ++) {
var subArray = Array.apply(null, Array(4)).map(
function () {
return Math.floor(Math.random() * sum)});
array.push(subArray);
}
return array;
}
var result = getCombinations(10,4);
So, guys, I have a strange question...
I have this code:
var valuesForLakewood = (function (m, k) {
return m[k] === undefined ? null : m[k];
})(this.lakewood, customerType);
var valuesForBridgewood = (function (m, k) {
return m[k] === undefined ? null : m[k];
})(this.bridgewood, customerType);
var valuesForRidgewood = (function (m, k) {
return m[k] === undefined ? null : m[k];
})(this.ridgewood, customerType);
lakewoodCost = weekdays * valuesForLakewood[0]
+ weekends * valuesForLakewood[1];
bridgewoodCost = weekdays * valuesForBridgewood[0]
+ weekends * valuesForBridgewood[1];
ridgewoodCost = weekdays * valuesForRidgewood[0]
+ weekends * valuesForRidgewood[1];
var hotel =
this.minCost(lakewoodCost, bridgewoodCost, ridgewoodCost);
I just need to clean it up a little bit. I repeat the same function over and over again and I would like your opinion on how I can clean this up a little bit, reducing the size of my code. Any thoughts? Thanks in advance!
Use a single function to extract the values from the object, two arrays instead of six standalone variables, destructuring to make the total cost operation more understandable, and then spread the resulting array into minCost:
const getVal = obj => obj[customerType] === undefined ? null : obj[customerType];
const values = [this.lakewood, this.bridgewood, this.ridgewood].map(getVal);
const costs = values.map(([weekdayCost, weekendCost]) => weekdays * weekdayCost + weekends * weekendCost);
const hotel = this.minCost(...costs);
I need to generate unique id numbers on the fly using javascript. In the past, I've done this by creating a number using time. The number would be made up of the four digit year, two digit month, two digit day, two digit hour, two digit minute, two digit second, and three digit millisecond. So it would look something like this: 20111104103912732 ... this would give enough certainty of a unique number for my purposes.
It's been a while since I've done this and I don't have the code anymore. Anyone have the code to do this, or have a better suggestion for generating a unique ID?
A better approach would be:
new Date().valueOf();
instead of
new Date().getUTCMilliseconds();
valueOf() is "most likely" a unique number. http://www.w3schools.com/jsref/jsref_valueof_date.asp.
The shortest way to create a number that you can be pretty sure will be unique among as many separate instances as you can think of is
Date.now() + Math.random()
If there is a 1 millisecond difference in function call, it is 100% guaranteed to generate a different number. For function calls within the same millisecond you should only start to be worried if you are creating more than a few million numbers within this same millisecond, which is not very probable.
For more on the probability of getting a repeated number within the same millisecond see https://stackoverflow.com/a/28220928/4617597
If you just want a unique-ish number, then
var timestamp = new Date().getUTCMilliseconds();
would get you a simple number. But if you need the readable version, you're in for a bit of processing:
var now = new Date();
timestamp = now.getFullYear().toString(); // 2011
timestamp += (now.getMonth < 9 ? '0' : '') + now.getMonth().toString(); // JS months are 0-based, so +1 and pad with 0's
timestamp += ((now.getDate < 10) ? '0' : '') + now.getDate().toString(); // pad with a 0
... etc... with .getHours(), getMinutes(), getSeconds(), getMilliseconds()
This can be achieved simply with the following code:
var date = new Date();
var components = [
date.getYear(),
date.getMonth(),
date.getDate(),
date.getHours(),
date.getMinutes(),
date.getSeconds(),
date.getMilliseconds()
];
var id = components.join("");
Here's what I do when I want something smaller than a bunch of numbers - change base.
var uid = (new Date().getTime()).toString(36)
This performs faster than creating a Date instance, uses less code and will always produce a unique number (locally):
function uniqueNumber() {
var date = Date.now();
// If created at same millisecond as previous
if (date <= uniqueNumber.previous) {
date = ++uniqueNumber.previous;
} else {
uniqueNumber.previous = date;
}
return date;
}
uniqueNumber.previous = 0;
jsfiddle: http://jsfiddle.net/j8aLocan/
I've released this on Bower and npm: https://github.com/stevenvachon/unique-number
You could also use something more elaborate such as cuid, puid or shortid to generate a non-number.
I use
Math.floor(new Date().valueOf() * Math.random())
So if by any chance the code is fired at the same time there is also a teeny chance that the random numbers will be the same.
In 2023, you can use the in-browser Crypto API to generate cryptographically strong random values.
function getRandomNumbers() {
const typedArray = new Uint8Array(10);
const randomValues = window.crypto.getRandomValues(typedArray);
return randomValues.join('');
}
console.log(getRandomNumbers());
// 1857488137147725264738
function getRandomNumbers() {
const typedArray = new Uint8Array(10);
const randomValues = window.crypto.getRandomValues(typedArray);
return randomValues.join('');
}
console.log(getRandomNumbers());
both Uint8Array constructor and Crypto.getRandomValues are supported on all major browsers, including IE11
This should do :
var uniqueNumber = new Date().getTime(); // milliseconds since 1st Jan. 1970
if you want a unique number after few mili seconds then use Date.now(), if you want to use it inside a for loop then use Date.now() and Math.random() together
unique number inside a for loop
function getUniqueID(){
for(var i = 0; i< 5; i++)
console.log(Date.now() + ( (Math.random()*100000).toFixed()))
}
getUniqueID()
output:: all numbers are unique
15598251485988384
155982514859810330
155982514859860737
155982514859882244
155982514859883316
unique number without Math.random()
function getUniqueID(){
for(var i = 0; i< 5; i++)
console.log(Date.now())
}
getUniqueID()
output:: Numbers are repeated
1559825328327
1559825328327
1559825328327
1559825328328
1559825328328
From investigating online I came up with the following object that creates a unique id per session:
window.mwUnique ={
prevTimeId : 0,
prevUniqueId : 0,
getUniqueID : function(){
try {
var d=new Date();
var newUniqueId = d.getTime();
if (newUniqueId == mwUnique.prevTimeId)
mwUnique.prevUniqueId = mwUnique.prevUniqueId + 1;
else {
mwUnique.prevTimeId = newUniqueId;
mwUnique.prevUniqueId = 0;
}
newUniqueId = newUniqueId + '' + mwUnique.prevUniqueId;
return newUniqueId;
}
catch(e) {
mwTool.logError('mwUnique.getUniqueID error:' + e.message + '.');
}
}
}
It maybe helpful to some people.
Cheers
Andrew
This also should do:
(function() {
var uniquePrevious = 0;
uniqueId = function() {
return uniquePrevious++;
};
}());
In ES6:
const ID_LENGTH = 36
const START_LETTERS_ASCII = 97 // Use 64 for uppercase
const ALPHABET_LENGTH = 26
const uniqueID = () => [...new Array(ID_LENGTH)]
.map(() => String.fromCharCode(START_LETTERS_ASCII + Math.random() * ALPHABET_LENGTH))
.join('')
Example:
> uniqueID()
> "bxppcnanpuxzpyewttifptbklkurvvetigra"
Always get unique Id in JS
function getUniqueId(){
return (new Date().getTime()).toString(36) + new Date().getUTCMilliseconds();
}
getUniqueId() // Call the function
------------results like
//"ka2high4264"
//"ka2hj115905"
//"ka2hj1my690"
//"ka2hj23j287"
//"ka2hj2jp869"
Updated for 2021, numbers and ids are not guaranteed to be unique but should be satisfactory unique enough:
(oh, and who knew something.toString(36) is even a thing 🙂)
// a pseudo-random floating number based on Date.now()
const generateRandomNumber = () =>
Math.log2(Date.now()) + Math.random();
console.log("a pseudo-random floating number based on Date.now():");
console.log(generateRandomNumber());
// a locally unique-ish HTML id
const generateUniqueId = () => `_${Date.now().toString(36)}${Math.floor(Number.MAX_SAFE_INTEGER * Math.random()).toString(36)}`;
console.log("a locally unique-ish HTML id:");
console.log(generateUniqueId())
// a pseudo-random BigInt
const generateRandomBigInt = () =>
BigInt(Date.now()) * BigInt(Number.MAX_SAFE_INTEGER) +
BigInt(Math.floor(Number.MAX_SAFE_INTEGER * Math.random()));
console.log("a pseudo-random BigInt:");
console.log(generateRandomBigInt().toString());
// same but base32-encoded (each char is 5 bits)
console.log("same but base32-encoded (each char is 5 bits):");
console.log(generateRandomBigInt().toString(32));
// extracting the "Date.now" timestamp of when it was generated:
console.log('extracting the "Date.now" timestamp of when it was generated:');
console.log(Number(generateRandomBigInt() / BigInt(Number.MAX_SAFE_INTEGER)))
// generate a run of random BigInt in ascending order
function generateRandomBigIntFactory() {
let count = 0, prev = 0;
return () => {
const now = Date.now();
if (now === prev) { ++count; }
else { count = 0; prev = now; }
return (BigInt(now) * BigInt(16384) + BigInt(count)) * BigInt(Number.MAX_SAFE_INTEGER) +
BigInt(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER));
}
}
// verify the order is ascending
const generate = generateRandomBigIntFactory();
let prev = 0;
for (let i = 0; i < 65536; i++) {
const num = generate();
if (num <= prev) console.log(`error: ${prev}, ${num}`);
prev = num;
}
console.log("the last random BigInt:");
console.log(prev.toString());
use this:for creating unique number in javascript
var uniqueNumber=(new Date().getTime()).toString(36);
It really works. :)
simple solution I found
var today = new Date().valueOf();
console.log( today );
This creates an almost guaranteed unique 32 character key client side, if you want just numbers change the "chars" var.
var d = new Date().valueOf();
var n = d.toString();
var result = '';
var length = 32;
var p = 0;
var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
for (var i = length; i > 0; --i){
result += ((i & 1) && n.charAt(p) ? '<b>' + n.charAt(p) + '</b>' : chars[Math.floor(Math.random() * chars.length)]);
if(i & 1) p++;
};
https://jsfiddle.net/j0evrdf1/1/
function UniqueValue(d){
var dat_e = new Date();
var uniqu_e = ((Math.random() *1000) +"").slice(-4)
dat_e = dat_e.toISOString().replace(/[^0-9]/g, "").replace(dat_e.getFullYear(),uniqu_e);
if(d==dat_e)
dat_e = UniqueValue(dat_e);
return dat_e;
}
Call 1: UniqueValue('0')
Call 2: UniqueValue(UniqueValue('0')) // will be complex
Sample Output:
for(var i =0;i<10;i++){ console.log(UniqueValue(UniqueValue('0')));}
60950116113248802
26780116113248803
53920116113248803
35840116113248803
47430116113248803
41680116113248803
42980116113248804
34750116113248804
20950116113248804
03730116113248804
Since milliseconds are not updated every millisecond in node, following is an answer. This generates a unique human readable ticket number. I am new to programming and nodejs. Please correct me if I am wrong.
function get2Digit(value) {
if (value.length == 1) return "0" + "" + value;
else return value;
}
function get3Digit(value) {
if (value.length == 1) return "00" + "" + value;
else return value;
}
function generateID() {
var d = new Date();
var year = d.getFullYear();
var month = get2Digit(d.getMonth() + 1);
var date = get2Digit(d.getDate());
var hours = get2Digit(d.getHours());
var minutes = get2Digit(d.getMinutes());
var seconds = get2Digit(d.getSeconds());
var millSeconds = get2Digit(d.getMilliseconds());
var dateValue = year + "" + month + "" + date;
var uniqueID = hours + "" + minutes + "" + seconds + "" + millSeconds;
if (lastUniqueID == "false" || lastUniqueID < uniqueID) lastUniqueID = uniqueID;
else lastUniqueID = Number(lastUniqueID) + 1;
return dateValue + "" + lastUniqueID;
}
let uuid = ((new Date().getTime()).toString(36))+'_'+(Date.now() + Math.random().toString()).split('.').join("_")
sample result "k3jobnvt_15750033412250_18299601769317408"
I came across this question while trying to find a simple UID generation technique that was also sortable (so I can order by uid and items will appear in order of creation / uid generation). The major problem with most (all?) of the solutions here is that they either rely on millisecond accuracy (at best) == clashes(!) or a pseudo-random number == clashes(!) && non-sortable(!).
Technique below uses micro-second precision where available (i.e. not where fingerprinting-resistance techniques are in play, e.g. firefox) combined with an incrementing, stateful suffix. Not perfect, or particularly performant for large numbers of IDs (see example with 1,000,000 below), but it works and is reversible.
// return a uid, sortable by creation order
let increment;
let tuidPrev;
const uid = (uidPrev) => {
// get current time to microsecond precision (if available) and remove decimals
const tuid = ((performance.timing.navigationStart + performance.now()) * 1000)
// convert timestamp to base36 string
.toString(36);
// previous uid has been provided (stateful)
if (uidPrev) {
tuidPrev = uidPrev.slice(0, 10);
increment = uidPrev.length > 10 ? parseInt(uidPrev.slice(10), 36) : 0;
}
// if tuid is changed reset the increment
if (tuid !== tuidPrev) {
tuidPrev = tuid;
increment = 0;
}
// return timed uid + suffix (4^36 values) === very unique id!
return tuid + ('000' + (increment++).toString(36)).slice(-4);
}
// EXAMPLE (check the console!)
const iterations = 1000000;
const uids = [];
const uidMap = {};
const timeMap = {}
const microMap = {};
let time = performance.now();
for (let i = 0; i < iterations; i++) {
const id = uid();
uids.push(id);
uidMap[id] = i;
timeMap[Date.now()] = i;
microMap[performance.now()] = i;
}
console.log(`Time taken: ${performance.now() - time}ms`);
console.log('Unique IDs:', Object.keys(uidMap).length.toLocaleString());
console.log('Clashing timestamps:', (iterations - Object.keys(timeMap).length).toLocaleString());
console.log('Clashing microseconds:', (iterations - Object.keys(microMap).length).toLocaleString());
console.log('Sortable:', !uids.slice().sort().find((id, i) => uids[i] !== id))
The usual way in which I generate unique IDs is by using Date.now();
const ID = Date.now();
console.log(ID);
The other way is by using a library as idgp which can be installed using npm.
The link: https://www.npmjs.com/package/idgp
Assumed that the solution proposed by #abarber it's a good solution because uses (new Date()).getTime() so it has a windows of milliseconds and sum a tick in case of collisions in this interval, we could consider to use built-in as
we can clearly see here in action:
Fist we can see here how there can be collisions in the 1/1000 window frame using (new Date()).getTime():
console.log( (new Date()).getTime() ); console.log( (new Date()).getTime() )
VM1155:1 1469615396590
VM1155:1 1469615396591
console.log( (new Date()).getTime() ); console.log( (new Date()).getTime() )
VM1156:1 1469615398845
VM1156:1 1469615398846
console.log( (new Date()).getTime() ); console.log( (new Date()).getTime() )
VM1158:1 1469615403045
VM1158:1 1469615403045
Second we try the proposed solution that avoid collisions in the 1/1000 window:
console.log( window.mwUnique.getUniqueID() ); console.log( window.mwUnique.getUniqueID() );
VM1159:1 14696154132130
VM1159:1 14696154132131
That said we could consider to use functions like the node process.nextTick that is called in the event loop as a single tick and it's well explained here.
Of course in the browser there is no process.nextTick so we have to figure how how to do that.
This implementation will install a nextTick function in the browser using the most closer functions to the I/O in the browser that are setTimeout(fnc,0), setImmediate(fnc), window.requestAnimationFrame. As suggested here we could add the window.postMessage, but I leave this to the reader since it needs a addEventListener as well. I have modified the original module versions to keep it simpler here:
getUniqueID = (c => {
if(typeof(nextTick)=='undefined')
nextTick = (function(window, prefixes, i, p, fnc) {
while (!fnc && i < prefixes.length) {
fnc = window[prefixes[i++] + 'equestAnimationFrame'];
}
return (fnc && fnc.bind(window)) || window.setImmediate || function(fnc) {window.setTimeout(fnc, 0);};
})(window, 'r webkitR mozR msR oR'.split(' '), 0);
nextTick(() => {
return c( (new Date()).getTime() )
})
})
So we have in the 1/1000 window:
getUniqueID(function(c) { console.log(c); });getUniqueID(function(c) { console.log(c); });
undefined
VM1160:1 1469615416965
VM1160:1 1469615416966
Maybe even better would be to use getTime() or valueOf(), but this way it returns unique plus human understandable number (representing date and time):
window.getUniqNr = function() {
var now = new Date();
if (typeof window.uniqCounter === 'undefined') window.uniqCounter = 0;
window.uniqCounter++;
var m = now.getMonth(); var d = now.getDay();
var h = now.getHours(); var i = now.getMinutes();
var s = now.getSeconds(); var ms = now.getMilliseconds();
timestamp = now.getFullYear().toString()
+ (m <= 9 ? '0' : '') + m.toString()
+( d <= 9 ? '0' : '') + d.toString()
+ (h <= 9 ? '0' : '') + h.toString()
+ (i <= 9 ? '0' : '') + i.toString()
+ (s <= 9 ? '0' : '') + s.toString()
+ (ms <= 9 ? '00' : (ms <= 99 ? '0' : '')) + ms.toString()
+ window.uniqCounter;
return timestamp;
};
window.getUniqNr();
let now = new Date();
let timestamp = now.getFullYear().toString();
let month = now.getMonth() + 1;
timestamp += (month < 10 ? '0' : '') + month.toString();
timestamp += (now.getDate() < 10 ? '0' : '') + now.getDate().toString();
timestamp += (now.getHours() < 10 ? '0' : '') + now.getHours().toString();
timestamp += (now.getMinutes() < 10 ? '0' : '') + now.getMinutes().toString();
timestamp += (now.getSeconds() < 10 ? '0' : '') + now.getSeconds().toString();
timestamp += (now.getMilliseconds() < 100 ? '0' : '') + now.getMilliseconds().toString();
Easy and always get unique value :
const uniqueValue = (new Date()).getTime() + Math.trunc(365 * Math.random());
**OUTPUT LIKE THIS** : 1556782842762
I have done this way
function uniqeId() {
var ranDom = Math.floor(new Date().valueOf() * Math.random())
return _.uniqueId(ranDom);
}
function getUniqueNumber() {
function shuffle(str) {
var a = str.split("");
var n = a.length;
for(var i = n - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
return a.join("");
}
var str = new Date().getTime() + (Math.random()*999 +1000).toFixed() //string
return Number.parseInt(shuffle(str));
}
in reference to #Marcelo Lazaroni solution above
Date.now() + Math.random()
returns a number such as this 1567507511939.4558 (limited to 4 decimals), and will give non-unique numbers (or collisions) every 0.1%.
adding toString() fixes this
Date.now() + Math.random().toString()
returns '15675096840820.04510962122198503' (a string), and
is further so 'slow' that you never get the 'same' millisecond, anyway.