How to prevent object to add duplicate value and stop excuting function - javascript

Hey guys i am adding data to the array as object but i wanted to if there is any duplicate item code so its stop excuting the function and return and if the the condition is true so its take the constructor value and add itno the data structure
This what i try to prevent it from adding the value but its not work as i want
function getNo(b){
for (const [key, value] of Object.entries(data)) {
let val = value.itemCode;
if(b === val){
alert('Its equalt to item code');
break;}else{ return b;};
}}
----What i want is-----
1) Check if value is duplicate or not from the itemCode constructor
2)If its a duplicate value so its should show and alert and stop excuting the function
3)And add this function into the addItem function to check its duplicate or not
4)I store value in the data array
var item = function(name,itemCode,stock){
this.name = name;
this.itemCode = itemCode;
this.stock = stock;
}
var data = [];
function addItem(name,itemCode,stock){
var Newitem = new item(name,itemCode,stock);
data.push(Newitem);
}
addItem('BlueTee',100,50);
addItem('Yellow tee',101,100);
addItem('BrownTee',102,120);

There are multiple ways to handle this. Your choice should depend on other use cases.
The easiest way is to define data as a javascript object instead of an array. This would require keys for each object. This would look like this:
var data = {};
function addItem(name, itemCode, stock){
var newItem = new item(name, itemCode, stock);
if(data[itemCode] === undefined)
data[itemCode] = newItem;
}
If you are going to later access data as an array, then you can instead iterate over the array for each insertion. This would look like this:
function addItem(name, itemCode, stock){
var newItem = new item(name, itemCode, stock);
if(!data.some(function(x => x.itemCode === itemCode)){
data.push(newItem);
}
}
This would be slower than a normal insertion especially for large datasets. If you are going to use a very large dataset and need to be able to access as an array, then I would use a hybrid between the two. The javascript object would be used for direct access to the object. A class-like implementation would be preferred for that, but without using oo, the code would look something like this:
var data = [];
var keys = {};
function addItem(name, itemCode, stock){
var newItem = new item(name, itemCode, stock);
if(keys[itemCode] === undefined){
data.push(newItem);
keys[itemCode] = data.length - 1;
}
}
This implementation also gets complicated if you are going to modify the array more than just adding elements

You can map the data array to itemCodes and see if it includes the itemCode of the new item, and if so return an empty object for your constructor. Then in your addItem function you can choose not to add the object to the array if the object is empty.
var item = function(name,itemCode,stock){
if (data.map(i => i.itemCode).includes(itemCode)) {
alert("This item has a duplicate itemCode");
return this;
}
this.name = name;
this.itemCode = itemCode;
this.stock = stock;
}
var data = [];
function addItem(name,itemCode,stock){
var Newitem = new item(name,itemCode,stock);
if (Newitem.name) data.push(Newitem); // check if an object was created with properties
}
addItem('BlueTee',100,50);
addItem('Yellow tee',101,100);
addItem('BrownTee',102,120);
addItem('RedTee',100,70); // this won't be added because of duplicate itemCode
console.log(data); // only contains BlueTee, Yellow tee, and BrownTee objects

Related

Insert element inside array

I have a function
checkName(output) {
output.filter((NewData) => {
return this.props.elements.filter((OldData) => {
if (NewData.key == OldData.key) {
NewData.name = OldData.name,
//there i need to add another element
// Need to add newData.number = OldData.number
}
return NewData
})
})
return output
}
and I call this function like:
const named = this.checkName(product.rows)
Now I need to add to my product's array that I passed to checkName the value "OldData.Number" to "newData.Number" that is not defined in product (so I need to create this field)
For example:
Product before the checkName function
product.rows = [NewData.name]
Product after the checkName function
product.rows = [NewData.name="value of OldData.name", NewData.number="value of OldData.number"]
How can I obtain this result?
There are 2 confusing things in your code:
You are using filter to execute an action in each member of the output array. However, filter should be used to... well, filter that array, meaning that is should not modify it, just return a sub-set of it. Instead, you might want to use forEach. However, taking into accound the next bullet, probably you want to use map.
You are modifying the array passed to the checkName function. This is confusing and can lead to hard-to-find bugs. Instead, make your function "pure", meaning that it should not mutate its inputs, instead just return the data you need from it.
I would suggest some implementation like this one:
checkName(output){
return output.map((NewData) => {
// find the old data item corresponding to the current NewData
const OldData = this.props.elements.find(x => x.key === NewData.key);
if (OldData) {
// If found, return a clone of the new data with the old data name
// This uses the spread syntax: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
return {
...NewData, // Clone the NewData object
name: OldData.name, // set the value found in OldData.name in the "name" field of the cloned object
number: OldData.number, // You can do the same for each field for which you want to replace the value cloned from NewValue
};
} else {
// Otherwise, just return a clone of the NewData
return { ...NewData };
}
}
}
The usage would be like this:
const named = this.checkName(product.rows)
Be aware that the product.rows array won't be modified!
You can get keys and values of the old object.
const keys = Object.keys(oldObject);
const values = Object.values(oldObject);
// or
const [keys, values] = Object.entries(oldObject);
After, you will create a loop with all keys of oldObject, and insert in newObject like a array.
keys.forEach( (key, index) => newObject[key] = values[index]);
// or
for (const [key, value] of Object.entries(object1)) {
newObject[key] = value
}
Use map like this.
checkName(output){
return output.map(( NewData) =>{
this.props.elements.forEach((OldData) => {
if (NewData.key == OldData.key) {
NewData.name = OldData.name;
NewData.number = OldData.number;
}
})
return NewData;
})
// return output;
}

Check if key exist

I have groupedTags and I need to add fields to it and add new tags across field.:
let groupedTags = {
'other': {}
}
if (!groupedTags.other[field]) {
groupedTags.other[field] = [];
}
groupedTags.other[field].push(tag);
I understand that it is necessary to initialize a new field to push new tag - Is there a more beautiful way to check if a field exists every time? I mean avoid explicit check. or is there nothing terrible about this check? there are just a lot of places where it can be repeated
Maybe you should investigate using Proxies for achieving your desired result.
Here's short example of doing so CodeSandbox -example
1) Create proxy handler to customise Object behaviour
const handler = {
set: function(obj, key, value) {
if (!obj[key]) {
obj[key] = [];
}
obj[key].push(value);
return true;
}
};
2) Assign Proxy to your Object
let groupedTags = {
other: new Proxy({}, handler)
};
Now assigning new value will go trough Proxy
groupedTags.other.b = "bar";
// {"other":{"b":["bar"]}}
If you want to create an array of elements on an empty (or not) object, you can try this. So you don't have to check if the property you want to push your element(s) already exists.
If it doesn't it will concat with an empty array, giving you an array with the one element, otherwise the value will be added to that array. Hope this helps.
const o = {};
const toAdd = [1,2,3,4];
toAdd.forEach((v) => {
o.other = (o.other || []).concat(v);
});
o.other2 = (o.other2 || []).concat(123);
console.log(o);
I believe there is no way around checking for a value + if needed initalizing it, other than doing it yourself explicitly.
You can take out one occurrence of groupedTags.other[field] using || like this:
let field = "foo", tag = "bar";
let groupedTags = {
'other': {}
}
// Get the existing items, or assign a new list & use it:
var items = groupedTags.other[field] || (groupedTags.other[field] = []);
items.push(tag);
console.log(groupedTags);
You could also make use of a helper method that encapsulates the check-and-init part:
let groupedTags = {
'other': {}
}
AddTag(groupedTags.other, "foo1", "bar1");
AddTag(groupedTags.other, "foo2", "bar2a");
AddTag(groupedTags.other, "foo2", "bar2b");
console.log(groupedTags);
// Can put this in a library.js
function AddTag(obj, field, tag) {
var items = obj[field] || (obj[field] = []);
items.push(tag);
}

Why Javascript object didn't change?

Can someone explain me this strange js behavior ?
All of this is in AngularJS.
I have helper function in my main app.js to simply return element from an array by its id:
var MyLib = MyLib || {};
MyLib.helpers = {
find: function(needle, stack) {
for (var i = 0; i < stack.length; i++) {
if(stack[i]._id === needle)
return stack[i];
}
return false;
}
}
Then I have factory and function to handle database change:
// categories are grabbed from db
var categories = [some array of objects];
// change is object returned from database that has all info about object as well as new object itself
function handleChange(change) {
var _category = MyLib.helpers.find(change.id, categories);
// if deleted, that part is ok
if(change.deleted) {
var idx = categories.indexOf(_category);
if(idx !== -1) {
categories.splice(idx, 1);
}
} else {
// if updated that part is weird
if(_category) {
_category = change.doc;
}
// if newly added that part is ok
else {
categories.push( angular.copy(change.doc) );
}
}
}
Why when I try to update element grabbed from categories array doesn't update in categories array ?
// categories ARE NOT updated after this
_category = change.doc;
and only when I refer to categories by index like this:
// categories ARE updated after this although _category is returned from this array by index (find function)
var idx = categories.indexOf(_category);
categories[idx] = change.doc;
I don't understand this...
You are overwriting the variable with a new value and any reference to prior value is gone.
Instead of overwriting the original object value with a new object you could update the existing object using angular.extend()
angular.extend(_category, change.doc);
I didn't analyze everything, but you should always have dot notation.
_category pass by value, and will not change when 'MyLib.hel ...' is changed
var _category = MyLib.helpers.find(change.id, categories);
something.category pass by reference, and will be changed when 'MyLib.hel ...' is changed
var something.category = MyLib.helpers.find(change.id, categories);

store value in JSON on button click

I am new in JSON, i am trying to save data using JSON. I have a list of element with some button when we click the button i want the corresponding value of button are save in JSON. I am also want to compare the title with already exists in JSON.
Demo Here
You can simply use a for loop to check if the element with that title is already there:
function alreadyAdded(itemTitle) {
for (var i = 0; i < objArray.length; i++) {
if (objArray[i].title === itemTitle) {
return true;
}
}
return false;
};
Also, you are not using a json object, just a JavaScript array.
Demo
try this
http://jsfiddle.net/Z3v4g/
var counter = 0;
var jsonObj = []; //declare object
$('.imgbtn').click(function () {
var title = $(this).parent().parent().find('span').html();
var image = $(this).parent().parent().find('img').prop('src');
for( var i=0; i<jsonObj.length; i++){
if( jsonObj[i].title == title ) return false;
};
counter++;
$('#lblCart').html(counter);
jsonObj.push({
id: counter,
title: title,
image: image,
description: 'Example'
});
});
I am assuming you want to store values in an array, and during a button click you want to check if the item already exists in the array. If this is true, then you can use the following code -
var counter = 0;
var jsonObj = []; //declare object
$('.imgbtn').click(function () {
var title = $(this).parent().parent().find('span').html();
var image = $(this).parent().parent().find('img').prop('src');
var match = $.grep(jsonObj, function (e) {
return e.title == title;
});
if (match.length > 0) {
// This title already exists in the object.
// Do whatever you want. I am simply returning.
return;
}
counter++;
$('#lblCart').html(counter);
jsonObj.push({
id: counter,
title: title,
image: image,
description: 'Example'
});
});
Notice that I have declared the array outside the callback function. This ensures that all the invocation of the callback operate on the same array object. Declaring it inside the callback was only making it available for a single callback invocation.
Also note that you are simply using an array to store plain JavaScript Objects.
Demo.
First:
var jsonObj = []; //declare object
This is not a JSON. This is an Array. JSON is just the notation of Javascript Object. To declare a object you should do:
var jsonObj = {};
or:
var jsonObj = new Object();
After this, you can approach what you asked doing this:
var counter = 0;
var jsonObj = new Object();
$('.imgbtn').click(function () {
var title = $(this).parent().parent().find('span').html();
var image = $(this).parent().parent().find('img').prop('src');
if (!(title in jsonObj)) { // if item is not in the object, (title in jsonObj) returns true of false
jsonObj[title] = { // When you have hundreds of items, this approach is way faster then using FOR loop, and if you need to alter the item or get one value, you can just call it by name: jsonObj['ABC'].image will return the path of the image
id: counter,
image: image,
description: 'Example'
}
counter++;
$('#lblCart').html(counter);
} else {
// Do what you want if the item is already in the list
alert('Item already in the list');
console.log(jsonObj[title]);
}
});
DON'T use FOR loops to do what you wan't, it will just slow down your application if the counter gets high.

Editing a jagged array in Javascript

I wish to simulate a taskbar (of running tasks/apps). I plan to store tasks something like this:
(function ()
{
var tasks = [];
addTask = function (taskName, taskWindow)
{
if (!tasks[taskName]) { tasks[taskName] = []; }
tasks[taskName].push({ taskWindow: taskWindow, taskName: taskName});
};
removeTask = function (taskName, taskWindow)
{
if (tasks[taskName])
{
//Somehow remove the object from the array
}
};
}());
How should I write removeTask() to remove the correct element from this jagged array?
I suggest using object to store your tasks, because it will make your ( specific to your requirement, I am not talking about Array vs Object) code cleaner and easier to maintain
var taskManager = (function(){
function taskManager(tasks){
// Do your tasks validation before passing to this.
var this.tasks = tasks || {}; // tasks value is not private here
}
// Assuming taskID would be unique value
taskManager.prototype.addTask = function (taskName, taskID){
if ( !this.tasks[taskID] ) {
this.tasks[taskID] = { taskID: taskID, taskName: taskName };
}
};
taskManager.prototype.removeTask = function (taskName, taskID){
if (this.tasks[taskID]){
delete this.tasks[taskID];
}
};
return taskManager;
})();
Usage:
var taskManager1 = new taskManager();
taskManager1.addTask(a,b);
taskManager1.removeTask(a);
Arrays are meant to have numeric indexes and you can use .splice() to remove a numeric indexed item from an array. Non-numeric indexes aren't really in the array, they end up just being properties on the array object and they can be removed with the delete operator.
If you don't have numeric indexes, then you should be using an object and use a property to index each item. When doing it that way, you can use delete tasks[taskName] to remove a property from the object.

Categories

Resources