How can I create a unique ID - javascript

I have a grid to which I can add or remove data For add I have this method
handelAddValueTransactionInput() {
let valueTransaction = this.state.valueTransaction;
valueTransaction.push({ id: valueTransaction.length + 1,Value:this.state.valueTransactionInput });
this.setState({ valueTransaction, valueTransactionInput: '' })
}
for delete:
deleteValueTransaction(data) {
let indexOfDeleted = -1;
let valueTransaction = this.state.valueTransaction;
this.state.valueTransaction.forEach((item, index) => {
if (item.id === data.id) {
indexOfDeleted = index;
}
})
valueTransaction.splice(indexOfDeleted, 1);
this.setState({
valueTransaction: valueTransaction
});
}
My problem is that when I have 3 data and I delete the second one and add one data twice .. the data that is added creates the same ID as the previous one
How can I create a unique ID for each?

You can use UUID
function create_UUID() {
var dt = new Date().getTime();
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = (dt + Math.random() * 16) % 16 | 0;
dt = Math.floor(dt / 16);
return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
return uuid;
}
for (let i = 0; i < 10; i++)
console.log(create_UUID());

If you want a random string, search for a "random string generator in JavaScript", I don't have it open now but there is such a function on another stack overflow question. One of the answers gives a nice function that returns a random string

For ids with length < 15 you can use following formula and combine it for large strings.
getRandomString = (length) => {
return Math.random().toString(36).substring(2, length + 2)
}

Related

Counter inkrementing

so I just learn how to code in JS, so i just want to warn you that my code may looks very awful for you.
I want a "class" that counts how often a number has been counted.
Example:
counter = new Counter();
counter.count(1);
counter.count(1);
counter.count(3);
Calling the getCounts gives the result:
counter.getCounts();
> 1: 2, 3: 1
My code works, but i have two problems.
Since I store it in an array, I can output the numbers not in order, but in the order they were called.
I don't think it's a pretty solution.
My code:
class Counter {
constructor(arr = []) {
this.arr = arr;
}
count(number) {
var posNumber = [];
var evenNumCheck = false;
var exactPos;
//Check if have the number already in the array
for (var i = 0; i < this.arr.length; i++) {
if (this.arr[i] === number) {
posNumber.push(i);
}
}
//posNumber we have the position of all the numbers that match our argument number
// we check which of them has an even position, only this can be the number we want
// since we save [number,count; number,count]
for (var i = 0; i < posNumber.length; i++) {
if (i % 2 === 0) {
evenNumCheck = true;
exactPos = i;
}
}
if (evenNumCheck) {
this.arr[exactPos + 1]++;
} else {
this.arr.push(number);
this.arr.push(1);
}
}
getCounts() {
var string = '';
for (var i = 0; i < this.arr.length; i += 2) {
if (i + 2 >= this.arr.length) {
string += this.arr[i] + ': ' + this.arr[i + 1];
} else {
string += this.arr[i] + ': ' + this.arr[i + 1] + ', ';
}
}
console.log(string);
}
}
Do you think this solution is ok or are there better solutions for it, which might also output the numbers in order?
The classic way is to use an object as said by #Orkhan Alikhanov
class Counter {
constructor () {
this.dic = {}
}
count (number) {
if (number in this.dic) {
this.dic[number]++
} else {
this.dic[number] = 1
}
}
getCounts () {
// instead of doing the trailing comma stuff
// make an array of string and join the array
const out = Object.entries(this.dic).map(entry => entry.join(':')).join(',')
console.log(out)
}
}
const counter = new Counter()
counter.count(1)
counter.count(1)
counter.count(2)
counter.getCounts()
You may prefer using a Map since semantically you just want to map a number to a count.
class Counter {
constructor () {
this.dic = new Map()
}
count (number) {
const count = this.dic.get(number)
this.dic.set(number, count ? count + 1 : 1)
}
getCounts () {
const out = [...this.dic.entries()].map(entry => entry.join(':')).join(',')
console.log(out)
}
}
const counter = new Counter()
counter.count(1)
counter.count(1)
counter.count(2)
counter.getCounts()
Finally, if you want the number printed not in the order they were inserted but with the "int" order, you have to sort the entries:
class Counter {
constructor () {
this.dic = new Map()
}
count (number) {
const count = this.dic.get(number)
this.dic.set(number, count ? count + 1: 1)
}
getCounts () {
const out = [...this.dic.entries()]
.sort((a, b) => a[0] - b[0]) // sort by first key (which is the number)
.map(entry => entry.join(':'))
.join(',')
console.log(out)
}
}
const counter = new Counter()
counter.count(2) // insert 2 before
counter.count(1)
counter.count(1)
counter.getCounts()

print like this * "a" -> "a1" * "aabbbaa" -> "a2b3a2"

I am new to js.
can you tell me how to print like this * "a" -> "a1" * "aabbbaa" -> "a2b3a2"
i tried with hash map but test cases failing.
providing my code below.
i am not good in hash map.
can you tell me how to solve with hash map so that in future I can fix it my self.
not sure what data structure to use for this one.
providing my code below.
const _ = require("underscore");
const rle = ( input ) => {
console.log("input--->" + input);
//var someString ="aaa";
var someString = input;
var arr = someString.split("");
var numberCount = {};
for(var i=0; i< arr.length; i++) {
var alphabet = arr[i];
if(numberCount[alphabet]){
numberCount[alphabet] = numberCount[alphabet] + 1;
}
else{
numberCount[alphabet] = 1;
}
}
console.log("a:" + numberCount['a'], "b:" + numberCount['b']);
}
/**
* boolean doTestsPass()
* Returns true if all the tests pass. Otherwise returns false.
*/
/**
* Returns true if all tests pass; otherwise, returns false.
*/
const doTestsPass = () => {
const VALID_COMBOS = {"aaa": "a3", "aaabbc":"a3b2c1"};
let testPassed = true;
_.forEach(VALID_COMBOS, function(value, key) {
console.log(key, rle(key));
if (value !== rle(key)) {
testPassed = false;
}
});
return testPassed;
}
/**
* Main execution entry.
*/
if(doTestsPass())
{
console.log("All tests pass!");
}
else
{
console.log("There are test failures.");
}
You could
match groups of characters,
get the character and the count and
join it to a string.
function runLengthEncoding(string) {
return string
.match(/(.)\1*/g) // keep same characters in a single string
.map(s => s[0] + s.length) // take first character of string and length
.join(''); // create string of array
}
console.log(['a', 'aaa', 'aaabbc'].map(runLengthEncoding));
This is a bit more understandable version which iterates the given string and count the characters. If a different character is found, the last character and count is added to the result string.
At the end, a check is made, to prevent counting of empty strings and the last character cound is added to the result.
function runLengthEncoding(string) {
var result = '',
i,
count = 0,
character = string[0];
for (i = 0; i < string.length; i++) {
if (character === string[i]) {
count++;
continue;
}
result += character + count;
character = string[i];
count = 1;
}
if (count) {
result += character + count;
}
return result;
}
console.log(['', 'a', 'aaa', 'aaabbc'].map(runLengthEncoding));
You can reduce the array into a multidimensional array. map and join the array to convert to string.
const rle = (input) => {
return input.split("").reduce((c, v) => {
if (c[c.length - 1] && c[c.length - 1][0] === v) c[c.length - 1][1]++;
else c.push([v, 1]);
return c;
}, []).map(o => o.join('')).join('');
}
console.log(rle("a"));
console.log(rle("aabbbaa"));
console.log(rle("aaaaaa"));
Your function rle doesn't return a result.
Also note, this implementation may pass the test cases you wrote, but not the examples you mentioned in your question: for the string "aabbaa" this will produce "a4b2", not " a2b2a2" .
A simpler solution:
function runLengthEncoding(str) {
let out = "";
for (let i = 0; i < str.length; ++i) {
let temp = str[i];
let count = 1;
while (i < str.length && str[i+1] == temp) {
++count;
++i;
}
out += temp + count;
} // end-for
return out;
}
console.log(runLengthEncoding("a"));
console.log(runLengthEncoding("aabbbaa"));
console.log(runLengthEncoding("aaaaaa"));

How to compare every number in an array against each other? (javascript)

I have a set of numbers which are displayed like followed;
var data = "615:415,600:400,600:400,300:300"
Each number represents an x/y coordinate, and I would like to add a value next to each one which is calculated based on the frequency of the number within a range.
So, I would like to be able to compare each value against all others in this string, and from this perform the following functions;
Remove the number from the string if it is a duplicate, and add :1
If the x/y numbers are both within a range of 15 against any other number, add:1
If there are no matches, add :0
Turn into array
So using the data string, it would be transformed to;
var data = "615:415:1, 600:400:2, 300:300:0"
I have been trying to do this using a reducer function, but I'm struggling with mainly step 2. I'm hoping someone can help out?
Thanks - Code + Plunk below!
http://plnkr.co/edit/zPW1844cLnUFAlEI77jq?p=preview
var result = [];
var data = "615:415,600:400,600:400,300:300"
var count = 0;
var reducer = function(p, c, i, a) {
if (p && p !== c) {
var _t = p.split(":");
result.push({
x: _t[0],
y: _t[1],
value: count
});
count = 0;
if (i === a.length - 1) {
_t = c.split(":");
result.push({
x: _t[0],
y: _t[1],
value: count
});
}
}
else {
count++;
}
return c
}
data.split(',').sort().reduce(reducer);
console.log(result)
You could use a step-by-step approach and split the string first in coordinates, generate a hash table for the coordinates with count and filter only unique coordinates.
Then compare each unique coordinates with each other and count if inside of a given range.
Later map the coordinates with the count and join to string.
var data = "615:415,600:400,600:400,300:300",
result = function (array) {
var i, j,
hash = Object.create(null),
unique = array.split(',').filter(function (a) {
var parts = a.split(':');
if (!hash[a]) {
hash[a] = [parts[0], parts[1], 0]; // [x, y, count]
return true;
}
hash[a][2]++;
});
for (i = 0; i < unique.length - 1; i++) {
for (j = i + 1; j < unique.length; j++) {
if (
Math.abs(hash[unique[i]][0] - hash[unique[j]][0]) <= 15 &&
Math.abs(hash[unique[i]][1] - hash[unique[j]][1]) <= 15
) {
hash[unique[i]][2]++;
hash[unique[j]][2]++;
}
}
}
return unique.map(function (a) {
return hash[a].join(':');
}).join(', ');
}(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Here's an alternative:
var data = "615:415,600:400,600:400,300:300";
var result = (function (s) {
var result = {};
var values = [];
// Process each value
s.split(',').forEach(function (v) {
var b = v.split(':');
// If a match, increment count by 2 (once for match and again for within 15)
if (result[v]) {
result[v].count += 2;
// Otherwise, just check for within 15
} else {
result[v] = {x:b[0], y:b[1], count:0};
values.forEach(function(xy, i){
if (xy[0]>= (b[0]-15) && xy[0] <= (+b[0]+15) &&
xy[1]>= (b[1]-15) && xy[1] <= (+b[1]+15) ) {
++result[xy.join(':')].count; // Increment for nearby only
}
})
values.push([b[0],b[1]]);
}
})
// Create required string format
return Object.keys(result).reduce(function(arr, key){
arr.push(key + ':' + result[key].count);
return arr;
},[]).join(', ');
})(data)
console.log(result);
All answers so far are good. I just would like to introduce a little variety by inventing an Array.prototype.withEachOther() method. Which just takes a callback an invokes the callback with each other item of the array being it's arguments as you may suggest. It works in place.
Array.prototype.withEachOther = function(cb){
this.map(function(e,i,a){
var t = a.slice();
t.splice(0,i+1);
t.map(function(f){
a[i] = cb(e,f);
});
});
return this;
};
var data = "615:415,600:400,600:400,300:300, 550 : 550".split(/\s*,\s*/)
.map(s => s.split(/\s*:\s*/).concat(0)),
cb = (f,s) => (Math.abs(f[0]-s[0]) <= 15 && Math.abs(f[1]-s[1]) <= 15 && (f[2]++, s[2]++),f);
result = data.reduceRight(function(p,c,i,a){
var fi = a.slice(0,i-a.length)
.findIndex(f => f[0] === c[0] && f[1] === c[1]);
fi !== -1 ? (a[fi][2] += ++c[2], a.splice(i,1))
: p.push(c);
return p;
},[])
.withEachOther(cb)
.reduce((p,c) => p += c[0]+":"+c[1]+":"+c[2]+", ","");
console.log(result);

Javascript repeatable random number based on multiple inputs

I am trying to create a function that takes 4 parameters and spits out a random number. But I want it so if the same 4 parameters are input, you will always get the same answer. The number should be between 0 and the max argument.
function random (x,y,z,max) {
output = ;
return Math.floor(output * max);
}
Is there any simple forumala I can use to get this? I tried to create one but it didn't look random at all, and would look very similar if you changed one parameter very slightly. I want it to be completely different, but repeatable.
hash function:
function hash (input){
input = 'random'+input;
var hash = 0;
if (input.length == 0) return hash;
for (i = 0; i < input.length; i++) {
char = input.charCodeAt(i);
hash = ((hash<<5)-hash)+char;
hash = hash & hash; // Convert to 32bit integer
}
return Math.abs(hash);
}
Generating an apparently unpredictable data from another is called "hashing"; restricting it to a range is called "modulo". Here is an easy way to do hashing using exponentiation:
const hashLim = () => {
const args = Array.prototype.slice.call(arguments);
const limit = args.shift();
var seed = limit - 1;
for (a in args) {
seed = Math.pow(args[a] + limit, seed) % limit
}
return seed;
}
document.write(hashLim(100, 4, 16, 64) + '<br/>')
document.write(hashLim(100, 5, 16, 64))
You can use some self made calculation for pseudo random values, like this example with pi and the taking of only the fractal part.
function Random(seed) {
var r = seed;
this.random = function () {
var v = r * Math.PI;
r = v - (v | 0);
return r;
}
this.random();
}
var i,
q = new Random(42),
r = new Random(42);
for (i = 0; i < 10; i++) {
document.write(q.random() +'<br>'+ r.random() + '<hr>');
}

Javascript: Random number out of 5, no repeat until all have been used

I am using the below code to assign a random class (out of five) to each individual image on my page.
$(this).addClass('color-' + (Math.floor(Math.random() * 5) + 1));
It's working great but I want to make it so that there are never two of the same class in a row.
Even better would be if there were never two of the same in a row, and it also did not use any class more than once until all 5 had been used... As in, remove each used class from the array until all of them have been used, then start again, not allowing the last of the previous 5 and the first of the next 5 to be the same color.
Hope that makes sense, and thanks in advance for any help.
You need to create an array of the possible values and each time you retrieve a random index from the array to use one of the values, you remove it from the array.
Here's a general purpose random function that will not repeat until all values have been used. You can call this and then just add this index onto the end of your class name.
var uniqueRandoms = [];
var numRandoms = 5;
function makeUniqueRandom() {
// refill the array if needed
if (!uniqueRandoms.length) {
for (var i = 0; i < numRandoms; i++) {
uniqueRandoms.push(i);
}
}
var index = Math.floor(Math.random() * uniqueRandoms.length);
var val = uniqueRandoms[index];
// now remove that value from the array
uniqueRandoms.splice(index, 1);
return val;
}
Working demo: http://jsfiddle.net/jfriend00/H9bLH/
So, your code would just be this:
$(this).addClass('color-' + (makeUniqueRandom() + 1));
Here's an object oriented form that will allow more than one of these to be used in different places in your app:
// if only one argument is passed, it will assume that is the high
// limit and the low limit will be set to zero
// so you can use either r = new randomeGenerator(9);
// or r = new randomGenerator(0, 9);
function randomGenerator(low, high) {
if (arguments.length < 2) {
high = low;
low = 0;
}
this.low = low;
this.high = high;
this.reset();
}
randomGenerator.prototype = {
reset: function() {
this.remaining = [];
for (var i = this.low; i <= this.high; i++) {
this.remaining.push(i);
}
},
get: function() {
if (!this.remaining.length) {
this.reset();
}
var index = Math.floor(Math.random() * this.remaining.length);
var val = this.remaining[index];
this.remaining.splice(index, 1);
return val;
}
}
Sample Usage:
var r = new randomGenerator(1, 9);
var rand1 = r.get();
var rand2 = r.get();
Working demo: http://jsfiddle.net/jfriend00/q36Lk4hk/
You can do something like this using an array and the splice method:
var classes = ["color-1", "color-2", "color-3", "color-4", "color-5"];
for(i = 0;i < 5; i++){
var randomPosition = Math.floor(Math.random() * classes.length);
var selected = classes.splice(randomPosition,1);
console.log(selected);
alert(selected);
}
var used = [];
var range = [0, 5];
var generateColors = (function() {
var current;
for ( var i = range[0]; i < range[5]; i++ ) {
while ( used.indexOf(current = (Math.floor(Math.random() * 5) + 1)) != -1 ) ;
used.push(current);
$(" SELECTOR ").addClass('color-' + current);
}
});
Just to explain my comment to jfriend00's excellent answer, you can have a function that returns the members of a set in random order until all have been returned, then starts again, e.g.:
function RandomList(list) {
var original = list;
this.getOriginal = function() {
return original;
}
}
RandomList.prototype.getRandom = function() {
if (!(this.remainder && this.remainder.length)) {
this.remainder = this.getOriginal().slice();
}
return this.remainder.splice(Math.random() * this.remainder.length | 0,1);
}
var list = new RandomList([1,2,3]);
list.getRandom(); // returns a random member of list without repeating until all
// members have been returned.
If the list can be hard coded, you can keep the original in a closure, e.g.
var randomItem = (function() {
var original = [1,2,3];
var remainder;
return function() {
if (!(remainder && remainder.length)) {
remainder = original.slice();
}
return remainder.splice(Math.random() * remainder.length | 0, 1);
};
}());

Categories

Resources