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.
Related
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);
});
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/:
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.
I want to insert an id in to an existing array of objects using underscorejs.
input array
var arr = [{name:"iPhone"}, {name:"Samsung"}];
expected output array
var arr = [{name:"iPhone", owner_id: "555"}, {name:"Samsung", owner_id: "555"}];
Tried following, its working but looking for a better way
devices = []
arr.forEach(function(data) {
var device = {};
device.owner_id = "555";
device.name= data.name;
devices.push(device )
})
zip them first and then using map
var arr = [{name:"iPhone"}, {name:"Samsung"}];;
var ageArr = [{owner_id: "555"},{owner_id: "555"}];
var newArr = _.zip(arr, ageArr).map(function(v) {
return _.extend(v[0], v[1]);
});
console.log(newArr);
<script src="http://underscorejs.org/underscore-min.js"></script>
No need to use underscore. Here is an easy way using the .map method. Each object returned inside the callback will be inserted into the devices array.
var devices = arr.map(function(data) {
var device = {};
device.owner_id = "555";
device.name= data.name;
return device;
})
If you console.log devices it will print (depending on data of course):
[{name:"iPhone", owner_id: "555"}, {name:"Samsung", owner_id: "555"}];
I've searched for an answer for this but haven't found one that cover this well with a good example.
I have a for loop:
for (var i=0;i<userProfileProperties.length;i++) {
if (userProfileProperties[i].indexOf("ValueImSearchingFor") {
console.log("GOTIT");
}
}
I'm trying to test each value in the loop to see if it contains a certain set of letters. If it doesn't, that value can be dropped. I can't get this to work. I've searched and have found examples but none seem do what I'm trying to do. or at least I've found no "working" example. I'm new to javascript.
So if my values in the loop returned normally would be: Jack User1, Jill User1, and Jerry User2; the values I want returned are all "User1"
I can't get this to work for:
while(userEnumerator.moveNext()){
var oUser = userEnumerator.get_current();
if(oUser.val.indexOf('ValueImsearchingFor') > -1)
{ ... do this} }
Use Array.prototype.filter() method available for arrays as below:
ES5
var res = userProfileProperties.filter(function (val) {
return val.indexOf("ValueImSearchingFor") > -1
});
ES6
let res = userProfileProperties.filter((val) => {
return val.indexOf("ValueImSearchingFor") > -1
});
let userProfileProperties = [
'ValueImSearchingFor 1',
'ValueImSearchingFor 2',
'test',
'ValueImSearchingFor 3',
'test 1'
];
let res = userProfileProperties.filter((val) => {
return val.indexOf("ValueImSearchingFor") > -1
});
console.log(res);