Javascript ES6 - Node Js - Associative Array - Objects use - wrong default order - node.js

I have a problem trying to use associative arrays/objects in node, I have the following code and I want to get the same order I use when i inserted elements.
var aa = []
aa[0] = 1
aa['second'] = 'pep'
aa['third'] = 'rob'
aa[4] = 2
for (var pos in aa) console.log (aa[pos])
But internally node put/sort first the numbers.
Look real execution :
1
2
pep
rob
I have created a parallel dynamic structure to solve this problem, but I'd like to ask for another solution or idea to get this target.
Regards.
Ricardo.

First of all, I'd recommend to use dictionary but not array, for dynamic keys:
var aa = {};
Elements are listed as its default order. You could check its default order with:
var keys = Object.keys(aa);
for (var i = 0; i < keys.length; i++) {
console.log(keys[i]);
}
If the default order is needed as the same order when inserting elements, try this to save the inserting order in another array:
var aa = {};
var keys = [];
aa[0] = 1
keys.push(0);
aa['second'] = 'pep'
keys.push('second');
aa['third'] = 'rob'
keys.push('third');
aa[4] = 2
keys.push(4);
for (var i = 0; i < keys.length; i++) {
console.log(aa[keys[i]]);
}

You may also want to give some ES6 features a try. Given you want to store data in a hash-like data structure that preserves the order I would recommend to give Map a try:
var map = new Map();
map.set(0, 1);
map.set('second', 'pep');
map.set('third', 'rob');
map.set(4, 2);
for (var [key, value] of map) {
console.log(key, value);
}
map.forEach(function (value, key) {
console.log(key, value);
});

nodejs arrays are just objects with numbers as keys and some added functions to their prototype. Also assoc. arrays are usually two arrays with values hinged together via a common index. for example:
let a = [1,2,3];
let b = ["one","two","three"];
also try to get away from looking through arrays with for loops. use the plethora of functions available to you via the prototype. for loops also iterate through enumerable properties on the objects prototype, so a for loop would incorrectly also iterate through that.

Related

Remove Array Json object elements

Here I have two arrays
var arry1 = [{id:1,name:"muni"},{id:2,name:"Anji"}, {id:3,name:"vinod"},{id:4,name:"anil"}];
var arry2 = [{id:3},{id:1}];
I want the following results
arry1= [{id:2,name:"Anji"},{id:4,name:"anil"}]
Should be remove second selected elements in first array
You can use Array.filter to remove any element that is present in arry2. We can create a Set of id elements to filter out, this will be more efficient for larger arrays:
var arry1 = [{id:1,name:"muni"},{id:2,name:"Anji"}, {id:3,name:"vinod"},{id:4,name:"anil"}];
var arry2 = [{id:3},{id:1}];
// Filter out any elements in arry1 that are also present in arry2, first create a Set of IDs to filter
const idsToFilter = new Set(arry2.map(el => el.id));
const result = arry1.filter(el => !idsToFilter.has(el.id));
console.log("Result:", result)
While removing from an array, you should iterate backwards over it.
for (let i = arry1.length - 1; i >=0; i--) {
...
}
This ensures that no elements are skipped after an element is removed. See also this other question for more info on this.
Now for each element of arry1 we want to check whether it should be removed.
let idsToRemove = arry2.map(e => e.id); // [3, 1]
for (let i = arry1.length - 1; i >=0; i--) {
if (idsToRemove.includes(arry1[i].id) {
// it should be removed
arry1.splice(i, 1);
}
}
Something like the above should then work for your problem. For easier understanding of the code, I first mapped arry2 to only the IDs, but of course you can also use another loop to see whether there is a match. The most important take-away is that to safely remove from an array while iterating it, you need to iterate from the last to the first element.
Try this it will work, here filter will filter out only those array element which doesn't exist in arry2
var myArray = arry1.filter(ar => !arry2.find(el => (el.id === ar.id) ))

Pick unique random numbers in node/express js

Have to pick unique random numbers from a given array of numbers. We have a list of numbers from that system has to pick unique random numbers.
Should have an option to input count, like if we give 3 system should pick 3 numbers from the given list.
Is there any available library?
const crypto = require('crypto');
const yourNumbers = [1,2,5,3,4,5,67,34,5345,6623,4234];
let selectedNumbers = [];
let i = 0;
const numbersRequired = 4;
while (i < numbersRequired){
const pos = crypto.randomBytes(4).readUInt32BE()%yourNumbers.length;
if (selectedNumbers.includes(yourNumbers[pos])) {
continue;
}
i++;
selectedNumbers.push(yourNumbers[pos]);
}
console.log(selectedNumbers)
I won't describe the code as it's self explanatory. Also handle the scenario where you cannot pick the required amount of numbers when the yourNumbers is too short. Also change the byte size if your number list is huge
const count = 8
pickedNumbers = [];
randomNumberList = [5,7,22,45,77,33,7,33,11,22,53,46,86,57,88];
for (i =0; i< count ; i++){
const randArrayIndex = Math.floor(Math.random() * randomNumberList.length);
pickedNumbers.push(randomNumberList[randArrayIndex]);
}
console.log(pickedNumbers);
It's a simple calculation. no need for an external library. You can use the random function of the Math object to generate a random number in js. It will return a number between 0 and 1. multiply it with the length of your array list. then it will give you a random index value from the range 0 - your array length. you can use push method of array object to push the numbers you are generating into an empty array.
control how many times you want this to happen with a loop setting the count value by users' input.

How to create a big list of different UUIDs, efficiently?

I want to generate tickets for an event. I need to generate a lot of them and I decided to have the ticket number as UUIDs. The question is how to generate a big list of UUIDs and it to be different.
I know the easy way to just check every new UUID generated in the already existing list, but this is not very performance friendly. :)
I am using NodeJS with UUID v4.
Thank you!
You could use home-grown UUID function, which is guaranteed to be unique pseudo-random integer in the range [0...2128). Below is one based on Linear Contguential Generator. Constants are taken from here or here. You only need to keep previous number/UUID at hands to generate next one, no need to check because it will be repeated only after full period of 2128.
Code relies on BigInt, tested with node v12
const a = 199967246047888932297834045878657099405n; // should satisfy a % 8n = 5n
const c = 1n; // should be odd
const m = (1n << 128n);
const mask = m - 1n;
function LCG128(state) {
return (BigInt(state) * a + c) & mask; // same as % m
}
q = 7654321n; // seed
q = LCG128(q);
q.toString(16); // first UUID
q = LCG128(q);
q.toString(16); // second UUID
q = LCG128(q);
q.toString(16); // third UUID
UPDATE
Just to be a more philosophical on the issue at hands:
You could consider UUID4 to be black box and trust it - this is what #ChrisWhite proposed
You could consider UUID4 to be black box and distrust it - that is whatyou proposed to check in the list or answer by #KevinPastor
Make your own transparent box which produces numbers in the proper range and be unique - that is my proposal
Beauty of LCG approach is that, given good multiplier and carry, it uniquely and reversable maps range [0...2128) into itself (it could do that for 64bit numbers, with different a, c, or 32bit numbers and so on and so forth). You could even use counter as input starting with 0 up to 2128-1 and it will produce non-repeatable numbers in the same range filling whole [0...2128). So you know that if you either chain it with previous uuid, or use counter, there is 0 chances of collision.
You can create an empty object and every time you generate a UUID, you add an attribute to that object where the key is the generated UUID. When you will generate another UUID, you just have to check if the object attribute is undefined or not to see if it's already used.
const uuids = [];
let uuidUsed = {};
const size = 10;
for (let i = 0; i < size; i++) {
let uuid = uuidv4();
while (uuidUsed[uuid] !== undefined) {
uuid = uuidv4();
}
uuidUsed[uuid] = true;
}
here’s a list of 446,538 IPs formatted in the following way: | id | date | name | uuid | ip |
https://minerlock.com/lock/F50f4b8d8e27e

Node.js variables being changed without any operations performed on them

I am using a node.js server for a multiplayer synchronized dice, but i am having some strange problems with variables changing that are not referenced or used...
var origonalRolls = rolls;
//identify epic fails
var epicFails = [];
for(var r = 0; r < rolls.length; r++)
if(rolls[r] === 1)
epicFails.push(r);
console.log("TEST 1 :: " + JSON.stringify(rolls));
console.log("TEST 2 :: " + JSON.stringify(origonalRolls));
//remove epic fails and the corresponding heighest
if(epicFails.length > 0){
for(var i = epicFails.length-1; i >= 0; i--){
rolls.splice(epicFails[i], 1);
if(rolls[rolls.length-1] >= success)
rolls.splice(rolls.length-1, 1);
}
}
console.log("TEST 3 :: " + JSON.stringify(rolls));
console.log("TEST 4 :: " + JSON.stringify(origonalRolls));
the above should find any element in the rolls array which is 1 and then add it to epicFails. it should then remove it from rolls as well as the heighest remaining roll. (note, rolls is sorted numerically)
for some reason the output of this segment of code is as follows:
TEST 1 :: [1,1,2,3,3,6,7,7,9,9]
TEST 2 :: [1,1,2,3,3,6,7,7,9,9]
TEST 3 :: [2,3,3,6,7,7]
TEST 4 :: [2,3,3,6,7,7]
I am unsure why rolls and origonalRolls start the same and end the same. I am only using rolls.
Any help and/or explanation to this problem is welcome, it's been troubling me for a long time now...
In Javascript Arrays and Objects are only shallow copied - which means that an array (rolls) copied from another array (originalRolls) is only a reference to originalRolls - it is not an entirely new array, and modifying values in one will affect values in the other.
You will need to implement a deep copy function to create an entirely new array based off another. There are numerous imlementations of deep copying arrays/objects both here and elsewhere on the net - here is one of them from a quick Google.
Replace var origonalRolls = rolls; with:
var origonalRolls = [];
for (var i = 0, len = rolls.length; i < len; i++) {
origonalRolls[i] = rolls[i];
}

Weird memory usage on Node.js

This simple code stores 1 million strings (100 chars length) in an array.
function makestring(len) {
var s = '';
while (len--) s = s+'1';
return s;
}
var s = '';
var arr = [];
for (var i=0; i<1000000; i++) {
s = makestring(100);
arr.push(s);
if (i%1000 == 0) console.log(i+' - '+s);
}
When I run it, I get this error:
(...)
408000 - 1111111111111111111 (...)
409000 - 1111111111111111111 (...)
FATAL ERROR: JS Allocation failed - process out of memory
That's strange 1 million * 100 are just 100 megabytes.
But if I move the s = makestring(100); outside the loop...
var s = makestring(100);
var arr = [];
for (var i=0; i<1000000; i++) {
arr.push(s);
if (i%1000 == 0) {
console.log(i+' - '+s);
}
}
This executes without errors!
Why? How can I store 1 Million objects in node?
In the moment you move the String generation outside the loop, you basically just create one String and push it a million times into the array.
Inside the array, however, just pointers to the original String are used, which is far less memory consuming then saving the String a million times.
Your first example builds 1000000 strings.
In your second example, you're taking the same string object and adding it to your array 1000000 times. (it's not copying the string; each entry of the array points to the same object)
V8 does a lot of things to optimize string use. For example, string concatenation is less expensive (in most cases) than you think. Rather than building a whole new string, it will typically opt to connect them i a linked list fashion under the covers.

Resources