How to use multiple Nodelists with forEach method - javascript

I'm working on a project that is basically a e-store, with a bin. What I'm trying to do is send a POST request to the server with my items from the bin.
I have an empty array. I also have 3 Nodelists, I want to reach their values, textContent, dataset and nest all of them in my empty array.
This is the array:
var products = { Lines: [ ] };
What I've tried so far:
const prName = this.parentNode.parentNode.querySelectorAll('.product-name-link');
const prInput = this.parentNode.parentNode.querySelectorAll('.product-quantity-input');
const prPrice = this.parentNode.parentNode.querySelectorAll('.product-price-total');
prName.forEach(product => products.push(product.dataset.id))
prInput.forEach(product => products.Lines.push(product.value))
prPrice.forEach(product => products.Lines.push(product.textContent))
I want them to have a key=> value like in the example above.
The result that I need to get looks similar to this:
"Lines":[
{
"Assortiment":"1627aea5-8e0a-4371-9022-9b504344e724",
"Quantity":12678967.543233,
"SalePrice":12678967.543233,
"Warehouse":"1627aea5-8e0a-4371-9022-9b504344e724"
},
{
"Assortiment":"1627aea5-8e0a-4371-9022-9b504344e724",
"Quantity":12678967.543233,
"SalePrice":12678967.543233,
"Warehouse":"1627aea5-8e0a-4371-9022-9b504344e724"
},
{
"Assortiment":"1627aea5-8e0a-4371-9022-9b504344e724",
"Quantity":12678967.543233,
"SalePrice":12678967.543233,
"Warehouse":"1627aea5-8e0a-4371-9022-9b504344e724"
}
],

... with everything already said in my comments, a working solution might look like that ...
const products = { Lines: [] };
const prName = this.parentNode.parentNode.querySelectorAll('.product-name-link');
const prInput = this.parentNode.parentNode.querySelectorAll('.product-quantity-input');
const prPrice = this.parentNode.parentNode.querySelectorAll('.product-price-total');
// create a product item with each iteration step ...
prName.forEach((elmNode, idx) => products.Lines.push({
Assortiment: elmNode.dataset.id,
Quantity: prInput.item(idx).value,
SalePrice: prPrice.item(idx).textContent
}));

Wrap them with Array.from() as follows:
Array.from(elements).forEach( function(el) {
console.log(el);
});

Related

Find the array length and create a custom line of code?

Here is my code:
const json = `{"BTC":{"available":0.00024868,"onOrder":0,"btcValue":0.00024868,"btcTotal":0.00024868},"LTC":{"available":0,"onOrder":0,"btcValue":0,"btcTotal":0},"ETH":{"available":0,"onOrder":0,"btcValue":0,"btcTotal":0},"NEO":{"available":0,"onOrder":0,"btcValue":0,"btcTotal":0},"BNB":{"available":0.08943066,"onOrder":0,"btcValue":0.0004663808919,"btcTotal":0.0004663808919}}`;
const data = JSON.parse(json);
var Table = require('cli-table');
const chalk = require("chalk");
const processed = Object.entries(data)
.filter(([, { available }]) => available > 0)
.map(([asset, { available, btcValue }]) => {
return { asset, available, btcValue };
});
const asArray = processed.map(Object.values);
//console.table(processed);
console.log(asArray);
console.log(asArray.length)
var table = new Table({
head: [chalk.green.bold('Coin'), chalk.green.bold('Available'), chalk.green.bold('BTC Value')]
, colWidths: [25, 25, 25]
});
table.push(
asArray[0], asArray[1]
);
var tableDisplay = table.toString();
console.log(tableDisplay);
I am trying to find a way of finding the asArray length, then putting each index in the table.push no matter how long it is,
So it would list asArray[0], and increase for each index of the array no matter what
the code currently works, but I have to know the length of the array in order to change the code each time.
you can set up a loop to loop through your asArray. A forEach loop will go through each of your element in the array until it reaches the end.
asArrays.forEach( element => {
table.push(element)
})

Merge and create an unique case sensitive array in javascript

It's a complicated scenario but will try to explain as much as possible. I have one object or arrays and one array. Now i have to compare selectedmodel values with mappedmodels, if the value(Case insensitive) matches with that object then fetch all the values of it and push it into selected model and combine both. Hope the example will clear what i am trying to achive.
var mappedModels = { 'CC605': ['cc605', 'CC605', 'cC605'], 'TC75X': ['TC75X'] };
var selectedModels = ['CC605', 'tc76'];
var desiredOutput = ["CC605", "tc76", "cc605", "cC605"];
I already wrote a solution to achieve it but i need a better code in terms of performance. Here is the solution:
function combineModelCases(selectedModels) {
const modelCases = [];
selectedModels.forEach(elm => {
const existingModels = mappedModels[elm.toUpperCase()];
if (existingModels) {
for (const key of existingModels) {
if (elm.toUpperCase() !== key) {
modelCases.push(key);
}
}
}
});
return selectedModels.concat(modelCases);
}
Here is Fiddle
I am using typescript and underscore js for your references. Any help would be very helpful.
You could use flatMap to get a flattened array of values for each key in selectedModels. Then, create a Set to get a unique collection models. Use Array.from() to convert the set to an array.
const mappedModels = { 'CC605': ['cc605', 'CC605', 'cC605'], 'TC75X': ['TC75X'] },
selectedModels = ['CC605', 'tc76'];
const models = selectedModels.flatMap(m => mappedModels[m] || []),
unique = Array.from(new Set([...selectedModels, ...models]));
console.log(unique)
you can do the following, :
var mappedModels = { 'CC605': ['cc605', 'CC605', 'cC605'], 'TC75X': ['TC75X'] };
var selectedModels = ['CC605', 'tc76'];
var desiredOutput;
function combineModelCases(selectedValue){
if(mappedModels.hasOwnProperty(selectedValue)){
desiredOutput = [... new Set([...mappedModels[selectedValue], ...selectedModels])]
return desiredOutput;
}
}
console.log(combineModelCases('CC605'));
here is the working demo : https://jsfiddle.net/wzo4d6uy/2/:

Filter/de-duplicate repeated variables

I am trying to add functionality into my JS script that de-duplicates the values returned. My original script here:
try{
var productList = dataLayer.basket.products.map(function(product) {
return product.travelType;
});
return productList.join('|');
}
catch(err){}
which returns values from an array like Bus|Bus|Train|Car|Bus
What I am trying to get to is an additional part of the script that would clean those values and de-duplicate them. For example the above script would only show "bus" once e.g. Bus|Train|Car
I have tried to do this using a filter but I am getting a null value being returned:
try{
var productList = dataLayer.basket.products.map(function(product) {
return product.travelType;
});
var filteredArray = productList.filter(function(item, pos){
return productList.indexOf(item)=== pos;
});
return filteredArray.join('|');
}
catch(err){}
Any guidance would be gratefully appreciated.
Thanks,
M
To filter duplicates in an array:
const array = ['toto', 'tata', 'tutu', 'toto'];
const filteredArray = [...new Set(array)];
console.log(filteredArray);
const remove_duplicates = (arr) => {
let setArr = new Set(arr);
let values = setArr.values();
return Array.from(values);
}
const example = ['Bus', 'Bus', 'Car', 'Bike'];
console.log(remove_duplicates(example).join('|'));
Your code is fine as is, the error must be in your data or in another part of your code that you didn't post:
const dataLayer = {
basket:{products:[
{travelType:'a'},
{travelType:'b'},
{travelType:'c'},
{travelType:'b'},
{travelType:'c'},
{travelType:'a'},
]}
}
var productList = dataLayer.basket.products.map(function(product) {
return product.travelType;
});
var filteredArray = productList.filter(function(item, pos){
return productList.indexOf(item)=== pos;
});
console.log(filteredArray.join('|'));
Using modern javascript:
let arr = ['Bus', 'Bus', 'Train', 'Car', 'Bus'];
let filteredArr= [... new Set(arr)];
let result = filteredArr.join('|');
I think the top answer in this question is just what you're searching for. Just apply that to your productList and it should get rid of all duplicate values.
Edit: oops, I just saw you were already doing exaclty that. But your code should work that way, I just tried it out in the console and it worked just as expected. The null values must be caused by some other part of your program.

Dynamically create array of objects, from array of objects, sorted by an object property

I'm trying to match and group objects, based on a property on each object, and put them in their own array that I can use to sort later for some selection criteria. The sort method isn't an option for me, because I need to sort for 4 different values of the property.
How can I dynamically create separate arrays for the objects who have a matching property?
For example, I can do this if I know that the form.RatingNumber will be 1, 2, 3, or 4:
var ratingNumOne = [],
ratingNumTwo,
ratingNumThree,
ratingNumFour;
forms.forEach(function(form) {
if (form.RatingNumber === 1){
ratingNumOne.push(form);
} else if (form.RatingNumber === 2){
ratingNumTwo.push(form)
} //and so on...
});
The problem is that the form.RatingNumber property could be any number, so hard-coding 1,2,3,4 will not work.
How can I group the forms dynamically, by each RatingNumber?
try to use reduce function, something like this:
forms.reduce((result, form) => {
result[form.RatingNumber] = result[form.RatingNumber] || []
result[form.RatingNumber].push(form)
}
,{})
the result would be object, with each of the keys is the rating number and the values is the forms with this rating number.
that would be dynamic for any count of rating number
You could use an object and take form.RatingNumber as key.
If you have zero based values without gaps, you could use an array instead of an object.
var ratingNumOne = [],
ratingNumTwo = [],
ratingNumThree = [],
ratingNumFour = [],
ratings = { 1: ratingNumOne, 2: ratingNumTwo, 3: ratingNumThree, 4: ratingNumFour };
// usage
ratings[form.RatingNumber].push(form);
try this its a work arround:
forms.forEach(form => {
if (!window['ratingNumber' + form.RatingNumber]) window['ratingNumber' + form.RatingNumber] = [];
window['ratingNumber' + form.RatingNumber].push(form);
});
this will create the variables automaticly. In the end it will look like this:
ratingNumber1 = [form, form, form];
ratingNumber2 = [form, form];
ratingNumber100 = [form];
but to notice ratingNumber3 (for example) could also be undefined.
Just to have it said, your solution makes no sense but this version works at least.
It does not matter what numbers you are getting with RatingNumber, just use it as index. The result will be an object with the RatingNumber as indexes and an array of object that have that RatingNumber as value.
//example input
var forms = [{RatingNumber:5 }, {RatingNumber:6}, {RatingNumber:78}, {RatingNumber:6}];
var results = {};
$.each(forms, function(i, form){
if(!results[form.RatingNumber])
results[form.RatingNumber]=[];
results[form.RatingNumber].push(form);
});
console.log(results);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
HIH
// Example input data
let forms = [{RatingNumber: 1}, {RatingNumber: 4}, {RatingNumber: 2}, {RatingNumber: 1}],
result = [];
forms.forEach(form => {
result[form.RatingNumber]
? result[form.RatingNumber].push(form)
: result[form.RatingNumber] = [form];
});
// Now `result` have all information. Next can do something else..
let getResult = index => {
let res = result[index] || [];
// Write your code here. For example VVVVV
console.log(`Rating ${index}: ${res.length} count`)
console.log(res)
}
getResult(1)
getResult(2)
getResult(3)
getResult(4)
Try to create an object with the "RatingNumber" as property:
rating = {};
forms.forEach(function(form) {
if( !rating[form.RatingNumber] ){
rating[form.RatingNumber] = []
}
rating[form.RatingNumber].push( form )
})

Find data from the strings of array2 in the array1 and save as new uniq array

I want to find strings that has data from the strings from the array 2 in the array1 and save result as separate uniq array.
As can you see I search for not exact values. From the array1 values I know only part of the information, and I want to find the complete strings, with that information, in array1. And at the end I want to save what I found. So, I don't have a problem with finding here, but a problem with saving in the valid single JSON.
Array examples:
Array #1:
{
"overflow": [
"id:address:name:location:email",
...
"id2:address2:name2:location2:email2"
]
}
Array #2:
[
"location:email",
...
"location2:email2"
]
Code:
resultArr: function() {
var arr1 = '/var/log/1.json';
var arr2 = '/var/log/2.json';
var arrResult = '/var/log/result.json';
var arr2Obj = JSON.parse(fs.readFileSync(arr2, 'utf-8'));
for (var i = 0; i < arr2Obj.length; i++) {
var arr1Obj = JSON.parse(fs.readFileSync(arr1, 'utf-8'));
arr1Obj.overflow = arr1Obj.overflow.filter(function(e) {
return e.includes(arr2Obj[i])
});
fs.appendFile(arrResult, JSON.stringify(arr1Obj, null, 2), 'utf-8');
}
}
My result:
[{
"overflow": [
"id:address:name:location:email"
]
}{
"overflow": [
"id54:address54:name54:location54:email56"
]
}{
"overflow": [
"id2:address2:name2:location2:email2",
"id6:address6:name6:location2:email2"
]
}
What I really want:
{
"overflow": [
"id:address:name:location:email",
"id54:address54:name54:location54:email56",
"id6:address6:name6:location2:email2",
"id2:address2:name2:location2:email2"
]
}
Instead of reading the file again and again, and appending to the result repeatedly, just do both actions only once. All the rest should happen in memory.
You will also get better results (no risk for duplicates in result) when you swap the loops: put the filter action as the outer loop. For the inner loop you can use some, since one match is enough for the entry to be included:
resultArr: function() {
var arr1 = '/var/log/1.json',
arr2 = '/var/log/2.json',
arrResult = '/var/log/result.json',
arr2Obj = JSON.parse(fs.readFileSync(arr2, 'utf-8')),
arr1Obj = JSON.parse(fs.readFileSync(arr1, 'utf-8'));
arr1Obj.overflow = arr1Obj.overflow.filter(function(e) {
return arr2Obj.some(function (f) {
return e.includes(f)
});
});
fs.writeFileSync(arrResult, JSON.stringify(arr1Obj, null, 2), 'utf-8');
}
At each iteration, you're creating a new object and appening it to a file.
JSON is not a good format to append to.
You're replacing the array instead of adding fields to it.
You can do it that way, it should work :
resultArr: () => {
let arr1 = '/var/log/1.json';
let arr2 = '/var/log/2.json';
let arrResult = '/var/log/result.json';
let arr2Obj = JSON.parse(fs.readFileSync(arr2, 'utf-8'));
let arr1Obj = JSON.parse(fs.readFileSync(arr1, 'utf-8')); // reading only one time
arr1Obj.overflow = arr2Obj.map(value => {
return arr1Obj.overflow.filter(e => return e.includes(value))
});
fs.writeFileSync(arrResult, JSON.stringify(arr1Obj, null, 2), 'utf-8'); //Writing only one time
}
Array.map() executes the closure for each field in your array and group all the values returned by the closure in another array.
I also replaced some keywords to make your code more ES6 compliant. I you really want to append, you should use CSV and not JSON.

Categories