How to check duplicate entries while adding to javascript object dynamically? - javascript

I have this AngularJS service.
demoService.getDemoData($scope.countEP).then(function (data) {
console.log(data);
for (var i = 0; i < data.length; i++) {
$scope.allEditorPicks.push(data[i]);
}
});
In this case,allEditorPicks is an array i have defined at the top of the code as follows.
$scope.allEditorPicks = [];
Here's the problem, when I'm using this array and printing these data, the array has same items. Duplicating. So I need a way to check existing items and stop adding them in that allEditorPicks array. We need to do this inside the for loop. I tried adding another loop inside the for loop and read the allEditorPicks array and check. But that doesn't work too.
demoService.getDemoData($scope.countEP).then(function (data) {
console.log(data);
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < $scope.allEditorPicks.length; j++) {
if ($scope.allEditorPicks[j].itemName == data[i].itemName) {
console.log("Item Exists")
} else {
$scope.allEditorPicks.push(data[i]);
}
}
}
});
This is the solution I tried. My browser got freezes and stopped working when I run this code. Please give me a solution.

first, sort the array by itemName and then remove the duplicates according to the order.
data = data.sort(function(a,b){
return a.itemName - b.itemName;
});
for (var i = 0; i < data.length; i++) {
if(data[i].itemName === data[i++].itemName){
console.log("Item Exists");
}else {
$scope.allEditorPicks.push(data[i]);
}
}

Try this :
demoService.getDemoData($scope.countEP).then(function (data) {
for(let i = 0; i < data.length; i++){
let found = $scope.allEditorPicks.find(elt => {
return elt.itemName === data[i].itemName;
});
if(!found){
$scope.allEditorPicks.push(data[i]);
}
}
})

Related

Why is this comparison not working, using google aps scripts?

The code below is not giving me the expected result.
It's to compare rows from two ranges and, although the second range's last row equals the one from the first range, it gives me false as the result.
var entryValuesCom = sheet.getRange(7, 1, LastRowSource, 9).getValues();
var dbDataCom = dbSheet.getRange(2, 1, dbSheet.getLastRow(), 9).getValues();
var entryVlArray = new Array();
var dbArray = new Array();
for (var r = 0; r < entryValuesCom.length; r++) {
if (entryValuesCom[r][0] != '' && entryValuesCom[r][5] != 'Daily Ledger Bal') {
entryVlArray.push(entryValuesCom[r]);
}
}
for (var a = 0; a < dbDataCom.length; a++) {
if (dbDataCom[a][1] != '' && dbDataCom[a][8] == bank) {
dbArray.push(dbDataCom[a]);
}
}
var duplicate = false;
loop1:
for (var x = 0; x < entryVlArray.length; x++) {
loop2:
for (var j = 0; j < dbArray.length; j++) {
if (JSON.stringify(entryVlArray) == JSON.stringify(dbArray)) {
duplicate = true;
break loop1;
}
}
}
Here's a snapshot of how the array is coming:
I've tried it using .join(), but still...
This is for thousands of rows, so is this going to do well performance wise?
I believe your goal as follows.
You want to compare the arrays of entryVlArray and dbArray using Google Apps Script.
When the duplicated rows are existing between entryVlArray and dbArray, you want to output duplicate = true.
Modification points:
When your script is modified, at if (JSON.stringify(entryVlArray) == JSON.stringify(dbArray)) {, all 2 dimensional arrays are compared. I think that this might be the reason of your issue. From your script, I think that it is required to compare each element in the 2 dimensional array.
When above points are reflected to your script, it becomes as follows.
Modified script:
From:
var duplicate = false;
loop1:
for (var x = 0; x < entryVlArray.length; x++) {
loop2:
for (var j = 0; j < dbArray.length; j++) {
if (JSON.stringify(entryVlArray) == JSON.stringify(dbArray)) {
duplicate = true;
break loop1;
}
}
}
To:
var duplicate = false;
for (var x = 0; x < entryVlArray.length; x++) {
for (var j = 0; j < dbArray.length; j++) {
if (JSON.stringify(entryVlArray[x]) == JSON.stringify(dbArray[j])) {
duplicate = true;
break;
}
}
}
console.log(duplicate)
By this modification, when each element (1 dimensional array) in the 2 dimensional array is the same, duplicate becomes true.
Note:
As other method, when an object for searching each row value is prepared, I think that the process cost might be able to be reduced a little. In this case, the script is as follows. Please modify as follows.
From:
var duplicate = false;
loop1:
for (var x = 0; x < entryVlArray.length; x++) {
loop2:
for (var j = 0; j < dbArray.length; j++) {
if (JSON.stringify(entryVlArray) == JSON.stringify(dbArray)) {
duplicate = true;
break loop1;
}
}
}
To:
var obj = entryVlArray.reduce((o, e) => Object.assign(o, {[JSON.stringify(e)]: true}), {});
var duplicate = dbArray.some(e => obj[JSON.stringify(e)]);
References:
reduce()
some()
Added:
About your following 2nd question,
AMAZING!!!! Would there be a way of capturing these duplicates in a pop up, using reduce() and some()?
When you want to retrieve the duplicated rows, how about the following script? In this case, I thought that filter() is useful instead of some().
Modified script:
var obj = entryVlArray.reduce((o, e) => Object.assign(o, {[JSON.stringify(e)]: true}), {});
// var duplicate = dbArray.some(e => obj[JSON.stringify(e)]);
var duplicatedRows = dbArray.filter(e => obj[JSON.stringify(e)]);
console.log(duplicatedRows)
In this modified script, you can see the duplicated rows at the log.
About a pop up you expected, if you want to open a dialog including the duplicated rows, how about adding the following script after the line of var duplicatedRows = dbArray.filter(e => obj[JSON.stringify(e)]);?
Browser.msgBox(JSON.stringify(duplicatedRows));

Nested for loop functioning

I have trouble understanding nested for loops
posts: [
{
title: 'lorem',
comments: [
{
content: 'lorem'
user: 'John'
},
...
]
},
...
]
My goal here is to get all the comments from a specific user, in all the posts.
Here is how I proceed (I'm using mongoose, I get the user from an auth middleware)
const postsList = await Post.find();
var userComments = [];
for (var i = 0; i < postsList.length; i++) {
if (postsList[i].comments.length > 0) {
for (var j = 0; j < postsList[i].comments[j].length; i++)
if (postsList[i].comments[j].user == req.user.id) {
userComments.push(comments[j]);
}
}
}
When I try this, I get a Cannot read property 'length' of undefined. I think my error is in the second for loop, but I can't get why. Any help please?
Mark Meyer in the comments is correct.
comments is an array inside of each post object. comments[j] would refer to an element inside the comments array. comments[j].length doesn't make sense because in order to run your nested j for loop, which iterates over the comments array, you want the length of the comments array, not the length of one of its elements.
Here's the line that needs to be fixed:
const postsList = await Post.find();
var userComments = [];
for (var i = 0; i < postsList.length; i++) {
if (postsList[i].comments.length > 0) {
// for (var j = 0; j < postsList[i].comments[j].length; i++)
// fixed version below
for (var j = 0; j < postsList[i].comments.length; i++)
if (postsList[i].comments[j].user == req.user.id) {
userComments.push(comments[j]);
}
}
}

how to get all values in for loop angular js

when I alert this I only get the last value of id. ican't findout where I'm going wrong
$scope.addToList = function (products,qty) {
if ($scope.order.length > 0) {
for (var i = 0; i < $scope.order.length; i++) {
$scope.Thx=$scope.order[i].id;
}}};
alert($scope.Thx);
Declare the $scope.Thx as an array first.
$scope.Thx = [];
$scope.addToList = function (products, qty) {
if ($scope.order.length > 0) {
for (var i = 0; i < $scope.order.length; i++) {
$scope.Thx.push($scope.order[i].id);
}
}
};
This line will overwrite the $scope.Thx for each iteration inside the loop.
$scope.Thx=$scope.order[i].id;
Now there are two ways to get the desired result.
1. If you want the separate alert for each item in the array then:
$scope.addToList = function (products,qty) {
if ($scope.order.length > 0) {
for (var i = 0; i < $scope.order.length; i++) {
$scope.Thx=$scope.order[i].id;
alert($scope.Thx);
}}};
2. If you want single alert for all the items.
declare $scope.Thx as an array first.
$scope.Thx = [];
$scope.addToList = function (products, qty) {
if ($scope.order.length > 0) {
for (var i = 0; i < $scope.order.length; i++) {
$scope.Thx.push($scope.order[i].id);
}
}
};
var tempVar="";
for(var i=0; i<$scope.Thx.length;i++)
{
tempVar += $scope.Thx[0]+"\n";
}
alert(tempVar);

JavaScript simplify for loop

I built the following for Loop and wanted to ask if there is a way to simplify it:
//data contains an array
var i = 0;
if(data.length >= 1) {
i = 1;
}
for (i; i <= data.length; i++) {
$('#img-thumb-id' + i).attr('src', data[i-1]);
}
I see that jQuery is used here, so you can use $.each
$.each(data, function(i, item){
var iteration = +i+1;
$('#img-thumb-id' + iteration).attr('src', item);
});
if you want to use vanilla JavaScript (no jQuery at all)
for (var i; i < data.length; i++) {
var iteration = +i+1;
document.getElementById('img-thumb-id'+iteration).src = data[i];
}
Or you can use:
for (var i in data) {
document.getElementById('img-thumb-id'+(+i+1)).src = data[i];
}
if(typeof data!=="undefined" && data && data.length>0) {
for (var i=0; i < data.length; i++) {
$('#img-thumb-id' + (i+1)).attr('src', data[i]);
}
}
The loop is fine, but I don't see why you don't just do:
if(data !== null){
for (var i = 0; i < data.length; i++) {
$('#img-thumb-id' + (i + 1)).attr('src', data[i]);
}
}
You don't need to do the first block of code in your question. It is more clear to people reading your code if you just do a standard for-loop starting from 0 and going up to the object.length.
You may also try this :
data.forEach(function(item, index){
$('#img-thumb-id' + (index+1)).attr('src', item);
});
Use simple foreach loop in JavaScript
//for eg. data array may be
var data = [1,2,3,4];
data.forEach(function(item, index){
$('#img-thumb-id' + (index+1)).attr('src', item);
});

How to build an object array by chaining http calls in AngularJS?

I want to build an array of objects but for each object I need multiple chained http calls. Eg:
var objects = [];
$http.get(/getDataUrl)
.then(function(data){
for(i = 0; i < data.length; i++)
{
objects[i] = { value1 : data.value }
}
for(i = 0; i < objects.length; i++)
{
http.get(objects[i].value1)
.then(function(data){
objects[i].value2 = data.value;
}
}
})
Any ideas how to properly execute this mess?
You will always get 'i' value to be the final index because the renderer will print it when the ajax request gives 200, this will take some time. And in that short time, the for loop would have been executed, therefore you will always get the last index for the value of 'i'
To solve this, you will have to use, closure inside loops
Modify your code like as follows,
var objects = [];
$http.get(/getDataUrl)
.success(function(data){
for(i = 0; i < data.length; i++)
{
objects[i] = { value1 : data.value }
}
for(i = 0; i < objects.length; i++)
{
(function(index) {
var currentURL = objects[i].value1;
$http.get(currentURL)
.success(function(data) {
// both currentURL and i value can be accessed here
console.log(currentURL);
console.log(index); // i value = index
objects[index].value2 = data.value;
});
})(i);
}
})
Now you have access of index inside the anonymous function. Hope this helps
You can try to use success instead of then, as $http isn't a standard promise :
var objects = [];
$http.get('/getDataUrl')
.success(function(data){
for(i = 0; i < data.length; i++)
{
objects[i] = { value1 : data.value }
}
for(i = 0; i < objects.length; i++)
{
http.get(objects[i].value1)
.success(function(data2){
objects[i].value2 = data2.value;
}
}
})
Try something like that :
Only one loop to rules them all ;)
$http.get(/getDataUrl)
.then(function(data){
for(i = 0; i < data.length; i++)
{
objects[i] = { value1 : data.value }
$http.get(objects[i].value1)
.then(function(data){
objects[i].value2 = data.value;
}
}
})

Categories

Resources