How do I make a loop check - javascript

I want to test if a local_key already exists, if it exists generate another local_key and check again
// Here I go throught an object and try to return a index
const local_key = messagesRow.map((message, key) => {
return message.local_key;
}).indexOf(message.local_key);
// If it returns 0 or bigger, it means that the local_key already exists
if(local_key >= 0){
message.local_key = Math.floor(Math.random() * 9999);
}
EDIT
I want to recheck every time, cause if the local_key exists and I generate another one, this new local_key maybe exists too

This will work, but you are iterating over the whole array, where you only need one match. I would recommend to use some javascript library like underscore (http://underscorejs.org/) which provides nice find function.
Using random number from 0 to 99999 is not a good solution - there is probability that you will generate duplicate number. Better choice would be some UUID / GUID
(see duscussion here: Create GUID / UUID in JavaScript? ) - and there will be no need at all to search for it in array as this is unique

The best way to generate a key is using uniqid
$id = md5(uniqid(date('d/m/Y H:i'), true));

Related

Generate random number that doesn't previously exist in a list

How can I create a random 16 digit number that doesn't previously exist in a list?
Let's say I have the following list:
const nums = [7856328870763265, 0107654389657487];
I need a function to generate random 16 digit numbers but that doesn't create duplicates.
I have the following:
const val = Math.floor(1000 + Math.random() * 9000).toString();
const random16digitnumber = +val+val+val+val;
console.log(random16digitnumber);
console.log(typeof random16digitnumber);
But im afraid at some point it will start creating duplicates. I'm using the random16digitnumber as a primary key in a SQL database for a small school project.
So going back to my example, how can I create a random 16 digit number that doesn't previously exist in an array?
I don't know much about JavaScript but I'm going to give you a general solution.
You need to use a loop statement to loop through the list to check whether the generated number is in the array. If it is not in the array then append/push it to the list. Else regenerate the random number.
Could have written it in php or python
I'll answer with an inline comment. I left your algo "as is". There might be reasons of why you're doing it this way; so I just implemented the logic you've wished for.
const nums = [7856328870763265, 0107654389657487];
const getNextRandomNumber = () => {
const val = Math.floor(1000 + Math.random() * 9000).toString();
const candidate = +val+val+val+val;
// the generated number is part of the list;
// recursively call this function to generate another one
// (this works like a loop, just using call recursion)
// until a number is found that is not part of the list
// then the return below this if() is triggered
// and the "good" candidate is returned
if (nums[candidate]) {
return getNextRandomNumber();
}
// parseInt makes sure the string is converted back to number
// making sure we're using base 10, even if the first digit
// might be 0
return parseInt(candidate, 10);
}
// push() adds an element to the array
// the return value (100% guaranteed to be collision free random number)
// is added via the function call. The function logic makes sure
// it is absolutely unique
nums.push(getNextRandomNumber());
If you want true randomness without duplicates, then you will need to every time check the list to ensure that it's not been included. Eventually that could become a drag on the system, but there's no alternative.
If you want a small enough chance of duplicates appearing that your code can likely ignore it (unless you have phenomenal volume), then GUIDs are probably your best bet... but these are far longer than 16 digits.
However, if you want numbers that appear at a casual glance to be random, although they are far from it, then a simple algorithm will give you all 10^16 numbers in a random-looking order. We can achieve this by taking subsequent numbers as a linear transform of the current ones. We can multiply our current value by some number, a and add another value, b, then take the last 16 digits to get the next value. So long as a and b have no common proper factors and neither has any common proper factors with 10^16, this process will cycle through all numbers from zero to 9999999999999999 in a seemingly random order.
The easiest way to ensure there are no common factors is just to choose two 16-digit primes, which we can do at a site like https://bigprimes.org/.
If we can keep hold of or easily look up the last-used id, then we can write it like this:
const a = BigInt ( '7791448648907857')
const b = BigInt ( '2320712743817497')
const c = BigInt ('10000000000000000')
const nextId = (previousId) =>
((a * BigInt(previousId) + b) % c)
.toString () .padStart ('0', 16)
const lastRecord = {id: '1234567890123456', more: 'fields'}
console .log (nextId (lastRecord .id))
If we can't easily keep track of the last id, but can keep a sequential counter, say n, we can always generate it using the formula
id_n = (a ** n + b * ((a ** n - 1) / (a - 1))) % c
That would involve efficiently managing modular exponentiation, but that's a well-solved problem and is easy enough to implement.
Don't forget that this is no only not cryptographically secure, it's far far from random. But it will give you random-looking number without repetitions.

jQuery Generate Short Unique Number

I am trying to generate a unique random string.
var string = Math.floor( Math.random() * 1000 ) + Date.now();
The above method which I am using right now gives me too long a string and I want a shorter unique one.
Here is a workaround to avoid the issue of repeated ids:
var GenRandom = {
Stored: [],
Job: function(){
var newId = Date.now().toString().substr(6); // or use any method that you want to achieve this string
if( this.Check(newId) ){
this.Job();
}
this.Stored.push(newId);
return newId; // or store it in sql database or whatever you want
},
Check: function(id){
for( var i = 0; i < this.Stored.length; i++ ){
if( this.Stored[i] == id ) return true;
}
return false;
}
};
jsFiddle
Based on Tushar's suggestion, (new Date().getTime()+'').substr(6,7) will give you a 7-digits unique number. Not random, but unique... at least for a certain time. Since it's based on timestamp, it is actually milliseconds time. Since the length is 7 digits, it will loop from 0000000 to 9999999 every 1000 seconds, that's roughly 17 minutes. But you can't expect a higher "level of uniqueness" with only 7 digits. It may be enough for your application, depending on what you want to achieve with that.
Edit
Following up with your comment : you want a unique SECOND number, so millisecond is no use to you (should have mentioned the seconds in your question).
You could give an invoice the number of the current second, which is (new Date().getTime()+'').substr(3,7). That would be perfect, if the unique number was not limited to 7 digits. This makes 9.999.999 possible seconds, which is... around 115 days.
With 9 digits, you could print unique invoices numbers every second for 316 years.
So in my opinion, your only solution is just to start counting invoices from 0000001, then 0000002, etc, and keeping track of that somewhere to ensure uniqueness. I don't get how generating a random number between 0 and 9.999.999 will make invoices numbering more efficient or easier to track.
For an invoice number you should guarantee a unique identifier no matter how long. In which case I'll suggest using an UUID/GUID. See http://guid.us/GUID/PHP for two implementations (windows-COM/non-windows). If you are not familiar with the concept of UUID, check wikipedia here: http://en.wikipedia.org/wiki/Universally_unique_identifier .
Another option for you is to use mysql's native uuid generator:
select uuid();
This you can also use in your insert queries, like:
insert into mytable (id, data) values (uuid(), 'mytext');
Of course your table structure needs to be adjusted. Personally I find it best to use traditional integer auto_inc id as primary key, along with a guid field to use in replication/export/etc as key.
EDIT:
There apparently is also a uuid_short() function in mysql (since 5.1.20).
SELECT UUID_SHORT();
92395783831158784
See https://dev.mysql.com/doc/refman/5.1/en/miscellaneous-functions.html#function_uuid-short

Safe way to check if array element exists?

I have a 2D array.
I currently access that array using notation such as:
myArray[5][9] (for example).
What is the safest way to check whether or not a certain array element exists?
For example, let's say I am looping through the array and retrieving a property of each array element like so:
myArray[5][9].firstName
I then come to myArray[9][11].firstName (for example) which doesn't exist. Clearly this will throw an exception as the element doesn't exist.
How can I deal with this? I'm not looping through the entire array (i'm accessing it's contents randomly and say using myArray.lengthin a for loop will not work.
Is there a JS function / method for checking whether or not an array element exists?
Thanks.
Safe call operator ?. looks fine. Warning: many, but not all implementations (and versions) of JavaScript supports it.
For your example it will looks like
myArray[5][9]?.firstName
EDIT: Thanks to Asaf's comment there is safer version
myArray?.[5]?.[9]?.firstName
like
if (!('firstname' in myArray[i][j])) { ... }
Just check it with if condition.
if(myArray[i][j].firstName){
}
You can use the hasOwnProperty method to check if an array item exists:
if (myArray.hasOwnProperty(x) && myArray[x].hasOwnProperty(y)) {
var name = myArray[x][y].firstName;
}
This checks both dimensions. If you know that the first index (x in the example) is always inside the range, you can skip the first test.
If you store some other values in the array also, you would need to check if the item has the firstName property:
if (myArray.hasOwnProperty(x) && myArray[x].hasOwnProperty(y) && myArray[x][y].hasOwnProperty('firstName')) {
var name = myArray[x][y].firstName;
}

How to check if an item exists in local storage without having the full path available?

I need to check wether a file exists in localStorage.
The filepath consists of
id.version
and I only have a the id value to test, which will be a 10 character string followed by the version which is of random length.
I'm used to checking for file existence server side using Coldfusion, where I can do something like this:
fileExists(expandPath(../some/path/to/a/file.*) )
where * would be any character.
Question:
Is something like this possible using regex, so I could test whether a file that contains the id parameter and any number of characters following the id exist? I don't need to retrieve the file itself, just know if there is at least one with matching id in the path.
Thanks for help!
You can iterate over each localstorage item and get the key with the .key() method and check if that contains the id string etc. or use a regex to do something similar, Figuring out how to check the value and not the key, if that's where the ID resides, should be trivial :
for (var i = 0; i < localStorage.length; i++){
if ( localStorage.key(i).indexOf(id) != -1 ) {
var item = localStorage.getItem(localStorage.key(i));
}
}

Get four unique items and add them to an array

I’m 100% certain this code has been working before. Now it strangely doesn’t.
The goal is to create a multiple choice quiz for a flashcard. I create an array to store the card's ids: the first one goes the current card id, then three other random ones. My goal is to make sure they don’t repeat either the first card or themselves.
This is how I do it:
// Array of cards’ ids to use
var randomCardsIds = [];
// Get the active card’s element id, add it to the array
randomCardsIds[0] = this.activeCardId;
// Get the current cards collection
var allCurrentCards = this.carouselEl.items.items;
// Get three random ids of other cards
var i = 0
while (i<3) {
// Get a random card element
var randomCardEl = allCurrentCards[Math.floor(Math.random() * allCurrentCards.length)];
// Get its id
var randomCardElId = randomCardEl.body.down('.card').id;
randomCardElId = randomCardElId.substring(randomCardElId.indexOf('_')+1);
console.log(randomCardElId, randomCardsIds, randomCardsIds.indexOf(randomCardElId));
// Make sure it is not in the array yet, and then add it
if (randomCardsIds.indexOf(randomCardElId) == -1) {
randomCardsIds.push(randomCardElId);
i++;
}
// Otherwise, the loop will have to run again
}
Basically, in a loop, for each item I check whether it already exists in the array or not. If it doesn’t, push it to the array, otherwise, run the loop again. Here is the console logging result:
Well, the first thing: it always shows the final state of the array: as if it is already filled with the results, which is weird. But the most important thing: the script does not recognise a duplicate (e.g. in the first result, 74 is repeated, and in the second to last, 47).
It only returns something different then -1, when it finds a match in the second position (returns 1, obviously). When a match is in a different position in the array, it always returns -1.
What am I doing wrong here?
Are you testing this in IE6? The problem is indexOf doesnot work with IE6.
For alternative you can check Best way to find if an item is in a JavaScript array?
A variation on a shuffling algoruthm seems to be the best bet here.

Categories

Resources