How to avoid duplicates to local storage in Angular.js - angularjs

I use Angular.js localstorage to store the values in local
Here is plnkr Demo
everything works fine but how to avoid inserting a product or a value twice? (how to avoid duplicates) while pushing a value to local

You just push items to an array without any further checks in cloneItem(). You can update its implementation to first check for duplicate (just a quick idea):
$scope.cloneItem = function (todo) {
// Check for duplicate on id
if($scope.$storage.notes.filter(function (note) {
return note.id === todo.id;
}).length > 0) {
return;
};
// Insert if not duplicate
$scope.$storage.notes.push({
"price": todo.price,
"id": todo.id,
"quan": todo.quan
});
}

I think you can use a shorter way than the Nicolas one:
$scope.cloneItem = function (todo) {
if ($scope.$storage.notes.indexOf(todo) == -1) {
//if the object is not in the array
$scope.$storage.notes.push({
"price": todo.price,
"id": todo.id,
"quan": todo.quan
});
}
//else you just do nothing
}

Related

How to Write a conditional statement in postman based on a value in an array

Within each element in an array, there may or may not be a value that I need to grab. If the value is not in one element, I want to go to the next element to look for it. I'd like to know how to write the statement to do that in my Postman test. I already know how to get the values when they exist, but I want to go through each element until I find what I'm looking for to put in the variable.
I've googled how to write the code, but I'm new to this and I'm having trouble.
var jsonData = JSON.parse(responseBody);
postman.setGlobalVariable("Date", jsonData.array[0].field[1]);
if (postman.setGlobalVariable("Date", jsonData.array[0].field[1]) === ???
else (postman.setGlobalVariable("Date", jsonData.array[1].field[1]);)
Hi, Here is a sample response (thanks!): You can see the first element does not have the value, "NeedTheseDates" that I need to grab, but the second element does.
"SampleArray": [
{
"Date": "2019-05-18T00:00:00.0000000-04:00",
"NeedTheseDates": [],
"Anything": "data",
"OnlyDate": "2019-06-03T00:00:00.0000000-04:00"
},
{
"Date": "2019-06-16T00:00:00.0000000-04:00",
"NeedTheseDates": [
"2019-07-02T00:00:00.0000000-04:00",
"2019-07-03T00:00:00.0000000-04:00",
"2019-07-04T00:00:00.0000000-04:00",
"2019-07-05T00:00:00.0000000-04:00",
"2019-07-06T00:00:00.0000000-04:00",
"2019-07-07T00:00:00.0000000-04:00",
"2019-07-08T00:00:00.0000000-04:00",
"2019-07-09T00:00:00.0000000-04:00",
"2019-07-10T00:00:00.0000000-04:00",
"2019-07-11T00:00:00.0000000-04:00",
"2019-07-12T00:00:00.0000000-04:00"
],
Not very sure about the problem statement. So trying all combinations
If there are only two cases where the value could be (index 0 or 1)
let someDate = jsonData.array[0].field[1] === '???' ?
jsonData.array[0].field[1] : jsonData.array[1].field[1];
postman.setGlobalVariable('Date', someDate);
If the length of array is dynamic but the date you are looking for in field is always at index 1
let someDate;
jsonData.array.forEach((element) => {
element.field[1] === '???' && (someDate = element.field[1]);
});
postman.setGlobalVariable('Date', someDate);
This will traverse all the items irrespective of whether it finds the correct element before. You can use some to stop that
let someDate;
jsonData.array.some((element) => {
if (element.field[1] === '???') {
someDate = element.field[1]);
return true; // this will stop the loop
}
});
postman.setGlobalVariable('Date', someDate);
If the length of array is dynamic and field is also dynamic
let someDate;
jsonData.array.some((element) => {
element.field.some((oneDate) => {
if (oneDate === '???') {
someDate = oneDate;
return true; // this will stop the inner loop
}
});
if (someDate) {
return true; // this will stop the outer loop
}
});
postman.setGlobalVariable('Date', someDate);

Most efficient way to check if any element in a JSON array contains a specific id?

I am using Node v8.1.3
I have a JSON array as following:
[
{
"id":99,
"name": "ABC"
},
{
"id": 187,
"name": "AXZ"
}
]
This array has around 213000 e=objects in it.
Also, the ids in the objects are not in any order or pattern.
Now, I want to find if a particular id matches any ID in the array? what is the fastest wait to do it?
I tried
isIdValid(id) {
console.log(id)
return this.list.filter((elem) => {
return elem.id == id
}).length > 0;
}
But this is taking over 4 seconds.
One option is to first sort the whole list (or insert it into a binary search tree) which takes some time but is only done once. and from there you can use binary search for the ID which is way faster.
here is a sample bst code for node:
js-bst
also here is a package that can be used to query json data list very faster: Defiant
Edit
actually creating a hash table is a faster solution than a bst; here is a sample code that does the job:
data = [
{
"id":99,
"name": "ABC"
},
{
"id": 187,
"name": "AXZ"
}
]
var hashCache = {};
data.forEach(function(item){
hashCache[item.id] = item.name
});
// Usage:
var id = '99';
var record = hashCache[id];
if (record) {
alert(record);
} else {
console.log('no match found');
}
you should also consider that this hash table only works if the IDs are unique. otherwise, you need to store a list of names in the hash table for each ID.
These are not the "Most efficient way to check". I'm posting here just as a reference about some ways to prepare the data to have a more performant search by a specific key.
Also is worth considering that in this script, Map can have a better performance, just because it is the last of all the executions. When its turn comes, V8 would have already been done some optimizations internally. So try to run each of them separately to have better findings.
'use strict';
////////////////////////
// GENERATE TEST DATA //
////////////////////////
const dataSet = [];
let count = 213000;
while(count--) dataSet.push({id: count});
let idToBeFound = 212999;
// //////////////////////////
// // Using Literal Object //
// //////////////////////////
console.time('creatingIndexAsLiteralObject');
const literalObjectKeyedByID = dataSet.map(item => ({[item.id]: true}));
console.timeEnd('creatingIndexAsLiteralObject');
console.time('isIdValidSeekingOnLiteralObject');
console.log('isIdValidSeekingOnLiteralObject :: Found?', isIdValidSeekingOnLiteralObject(idToBeFound, literalObjectKeyedByID));
console.timeEnd('isIdValidSeekingOnLiteralObject');
function isIdValidSeekingOnLiteralObject(id, list) {
return !!list[id];
}
// //////////////////////
// // Using Set Object //
// //////////////////////
console.time('creatingIndexAsSetObject');
const setObject = new Set(dataSet.map(item => item.id));
console.timeEnd('creatingIndexAsSetObject');
console.time('isIdValidSeekingOnSet');
console.log('isIdValidSeekingOnSet :: Found?', isIdValidSeekingOnSet(idToBeFound, setObject));
console.timeEnd('isIdValidSeekingOnSet');
function isIdValidSeekingOnSet(id, list) {
return list.has(id);
}
//////////////////////
// Using Map Object //
//////////////////////
console.time('creatingIndexAsMapObject');
const mapObjectKeyedByID = new Map();
dataSet.forEach(item => mapObjectKeyedByID.set(item.id));
console.timeEnd('creatingIndexAsMapObject');
console.time('isIdValidSeekingOnMap');
console.log('isIdValidSeekingOnMap :: Found?', isIdValidSeekingOnMap(idToBeFound, mapObjectKeyedByID));
console.timeEnd('isIdValidSeekingOnMap');
function isIdValidSeekingOnMap(id, list) {
return list.has(id);
}

filter through scope array ignoring certain items

I have a scope array called $scope.groups
$scope.groups = [{
id: 1,
name: "Group 1"
},
{
id: 2,
name: "Group 2"
}]
When I updated one of the groups I need to check if that updated group exists in the groups array however when i filter the array it checks the group i need to update as well so it outputs "Group exists".
function ifGroupExists(GroupName,GroupId) {
var match;
match = $scope.groups.filter(function (item) { return angular.lowercase(item.name) === angular.lowercase(GroupName); });
if (match.length > 0) {
console.log("group exists");
return true;
}
else {
console.log("group does not exists");
return false;
}
}
This code works if im adding a totally new group to the array however how do i edit this so that it doesnt check the group currently being updated and have it so it only checks the other groups to see if there is a match.
Can someone help? Im sure there is a simple way to do this. Just cant seem to figure it out..
It can be simple like, just pass the currently updating group to function as well, and ignore it in the filter.
Code should be like :
function ifGroupExists(groupName_filter, groupName_current) {
var match;
match = $scope.groups.filter(function (item) {
return (angular.lowercase(item.name) === angular.lowercase(groupName_filter) &&
angular.lowercase(item.name) !== angular.lowercase(groupName_current));
});
return (match.length > 0);
}
and I hope you need console.log only during development :), so return can be simplified.
Further: If you have groupName_current as $scope property, then use it directly, no need to pass.

Meteor return length of array in mongodb

In my users profile collection I have array with image objects in it.
A user can have a max of 3 images in their profile collection. If the user has 3, throw an error that the maximum has been reached. The user has the option to remove an image themselves in the frontend.
I thought the solution would be to check the length of the array with $size. if it's less then 3, insert the image, else throw error.
I'm using the tomi:upload-jquery package.
client:
Template.uploadImage.helpers({
uploadUserData: function() {
return Meteor.user();
},
finishUpload: function() {
return {
finished: function(index, fileInfo, context) {
Meteor.call('insert.profileImage', fileInfo, function(error, userId) {
if (error) {
// todo: display modal with error
return console.log(error.reason);
} else {
// console.log('success ' +userId);
// console.log('success ' + fileInfo);
}
});
}
};
}
});
The method (server) I use:
'insert.profileImage': function(postImage) {
check(postImage, Object);
// check array profile.images max 3
Meteor.users.update(this.userId, {
$push: {
'profile.images': postImage
}
});
},
You may do it with a function using the $where operator:
'insert.profileImage': function(postImage) {
var updateResults;
check(postImage, Object);
updateResults = Meteor.users.update(
{
_id : this.userId,
$where : 'this.profile.images.length < 3' //'this' is the tested doc
},
{
$push: {
'profile.images': postImage
}
});
if(updateResults === 0) {
throw new Meteor.Error('too-many-profile-images',
'A user can only have up to 3 images on his/her profile');
}
},
The Mongo docs warns about potential performance issues (if you run a JavaScript function on all documents of the store, you're in for bad surprises) but since we also search by _id I guess it should be fine.
This way, the update just doesn't run if the user has too many images. You can also check the number of affected document (the return value of the update) to know if something happened. If nothing (returns 0) happened, there's not many possibilities: The user has too many images.
Use the $exists operator to check the existence of all documents that have at least a fourth profile image array element (index position 3) with the dot notation. For example you could use it to check whether the size of the profile.image array is greater than 3 with the find() method as follows:
var hasSizeGreaterThanThree = Meteor.users.find(
{
'_id': this.userId,
'profile.image.3': { '$exists': true }
}).count() > 0;
So you could use that in your code as:
'insert.profileImage': function(postImage) {
check(postImage, Object);
// check array profile.images max 3
var hasSizeGreaterThanThree = Meteor.users.find(
{
'_id': this.userId,
'profile.image.3': { '$exists': true }
}).count() > 0;
if (!hasSizeGreaterThanThree){
Meteor.users.update(this.userId, {
$push: {
'profile.images': postImage
}
});
}
},

Firebase - How to update many children and not delete others in AngularFire

I want to use update() on firebase ref to update many children in one operation.
To do this I passed the object with values to change.
Here is the output of console.log(angular.toJson(change,1))
{
"10": {
"otherRubies": 30
},
"11": {
"otherRubies": 30
}
}
At the beginning i have:
Then i do:
var refUsers = new Firebase(FBURL).child('users/');
refUsers.update(change);
So i want to have:
but instead of that i get:
Is there any way to do that ?
Update is not a recursive operation. So it's calling set on the child paths. If you call update at users/, you're saying don't delete any keys under user/ which are not in my data, when you want to say, don't delete any keys in the child records of user/.
Instead, iterate the records and call update on each:
var refUsers = new Firebase(FBURL).child('users/');
for(key in change) {
if( change.hasOwnProperty(key) ) {
refUsers.child(key).update( change[key] );
}
}
With Firebase 3 you can do the update by writing :
update = {};
update['10/otherRubies'] = 30;
update['11/otherRubies'] = 30;
refUsers.update(change);
This way of updating the data is not in the documentation but it worked for me.
This is a sample of recursive update:
function updateRecursively(path, value) {
for (let key in value) {
if (value[key] instanceof Object) {
updateRecursively(`${path}/${key}`, value[key]);
} else {
firebase.database().ref(`${path}/${key}`).set(value[key]);
}
}
}
Usage:
updateRecursively('users', {
"10": {
"otherRubies": 30
},
"11": {
"otherRubies": 30
}
})

Resources