how do i stop duplicate data entry in array of object - javascript

I have an array with name validationValueIdValues so when user clicks on the input state ie. validationIdValue takes the value of individual input box. Now one user select on of option that is either Yes or No. The function creates an obj with key name equal to state, validationIdValue and value equal to users selection in short creates an obj like this
{08765d0f-2e7a-4fbd-9282-c38f5ddf8d8b: "NO"}
Then this object is pushed to validationValueIdValues variable. Now problem arises when user select same box and changes select value from NO to YES
{08765d0f-2e7a-4fbd-9282-c38f5ddf8d8b: "YES"}
Then this object is pushed to the validationValueIdValues variable without checking if previous same obj with key exist or not and if exist then delete that obj from array. I am using following code for this purpose but some how duplicate obj still exist in an array.
var validationValueIdValues = [] //as global variable
if (this.state.selectedOption === "YES") {
const attribute = {};
attribute[this.state.validationIdValue] = "YES";
if (validationValueIdValues.length > 0) {
validationValueIdValues.forEach((data, index) => {
if (Object.keys(data) == this.state.validationIdValue) {
validationValueIdValues.splice(index, 1);
validationValueIdValues.push(attribute);
}
});
} else {
validationValueIdValues.push(attribute);
}
}
I have used same if statement for this.state.selectedOption === "NO"

You will need to check all keys in the array to find the matching value. You don't need the code to be repeated for "YES" or "NO" as you mentioned. Something like this is generic enough to handle it
const validationValueIdValues = [] //as global variable
const addOrUpdateValidationValues = (newValidationValue) => {
if(!newValidationValue) {
return;
}
const keyOfNewValue = Object.keys(newValidationValue)[0]
let added = false
// loop through all values
for(const validationValue of validationValueIdValues) {
const keyOfCurrentValue = Object.keys(validationValue)[0]
if(keyOfNewValue === keyOfCurrentValue) {
// found that kind of key then just replace the value
added = true
validationValue[keyOfCurrentValue] = newValidationValue[keyOfNewValue]
}
}
// not added push
if(!added) {
validationValueIdValues.push(newValidationValue)
}
}
// ...
// when you have the select or what ever event
// just call
addOrUpdateValidationValues(this.state.selectedOption)

Use .findIndex() with .some() to see if the value exists in the array, if exists update the value or push the new value.
const array = [{'08765d0f-2e7a-4fbd-9282-c38f5ddf8d8b': "YES"}, {'tyhgsgsvbb': 'NO'}];
const found = array.findIndex((item) => Object.keys(item).some(key => key === 'tyhgsgsvbb'));
if (found) {
// toggle the value from yes to no, or vice versa
array[found] = array[found] === 'YES' ? 'NO' : 'YES'
} else {
array.push({newKey: 'newValue'});
}
console.log(array)

const newObject = {'08765d0f-2e7a-4fbd-9282-c38f5ddf8d8b': "NO"}
const array = [{'08765d0f-2e7a-4fbd-9282-c38f5ddf8d8b': "YES"}, {'tyhgsgsvbb': 'NO'}];
const items = array.filter(item => item['08765d0f-2e7a-4fbd-9282-c38f5ddf8d8b'])
if(allKeys.length>0) array[array.findIndex(items[0])] = newObject
else array[array.length] = newObject

You can try this!
const array=[{'08765d0f-2e7a-4fbd-9282-c38f5ddf8d8b': "YES"},{'08754d0f-2e7a-4fbd-9282-c38f5ddf8d8b': "YES"}];
let newValue = {'08765d0f-2e7a-4fbd-9282-c38f5ddf8d8b': "YES"};
const index = array.findIndex(e=>Object.keys(e).indexOf(Object.keys(newValue)[0])>-1);
if(index > -1){
array.splice(index,1,newValue); //Replacing the value
} else {
array.push(newValue);
}

'in' can be used to check for the key in array
// if key not in array then add to array
if ( !( 'mydata' in myArray) ) {
myArray['mydata'] = 99;
}

Related

check to see if every element inside an array is empty [duplicate]

This question already has answers here:
How to check if all array values are blank in Javascript
(10 answers)
Closed last month.
I am trying to check if the element is undefined and if its defined, all the elements inside it are empty, be it an array or nested arry or nested object
Here is the screenshot
https://prnt.sc/n412fbl0aUvv
My try till now
let validation=true;
for(let i=0;i<items.lenght;++i){
if(Object.keys(items[i]).length===0) {
validation =false;
break;
}
}
its not checking for everything here
There is at least an array of objects nested in the items object.
And you wish to validate the nested objects too.
So you need a recursive function to test the nested items. You also need to know when the recursion hits an array or an object.
Have a look at getType(), a function to get the type of an item. It's needed because typeof() returns object for both an object or an array. Based on the returned type, validation() (the recursive function) can send the right item to the next recursion until the item is not an array or object. It can then check if it is an empty string. It also could be a boolean, a number or a function but in those cases, they will not contain a string to be tested.
// Your item structure, as seen on the image in question
const items = {
paymentItem: [
{
billingAccountNum: "",
invoiceNumber: ""
}
],
transactionDate: "",
transactionId: ""
};
// Function to get an item type
const getType = (item) => {
let itemType = typeof(item)
if(itemType === "object"){
itemType = Array.isArray(item) ? "array" : "object"
}
return itemType
}
// The recursive function to turn isValid to false if there is one empty string.
const validation = (item) => {
if(getType(item) === "object"){
Object.keys(item).forEach((key) => validation(item[key])) // Recursion here.
return
}
if(getType(item) === "array"){
item.forEach((element) => validation(element)) // Recursion here.
return
}
if(item === ""){
isValid = false
}
}
// Validation variable
let isValid = true
// Validation function call
validation(items)
// Final result
console.log("first test:", isValid)
// ==============
// Let's do a second test where only one property is empty
const items2 = {
paymentItem: [
{
billingAccountNum: "",
invoiceNumber: 84566
}
],
transactionDate: "2023-01-15T00:20:00",
transactionId: "HS9873-1"
};
// Reset the validation variable
isValid = true
// Validation function call
validation(items2)
// Final result
console.log("second test:", isValid)

How to get the opposite property?

I have the following object with (always) 2 properties. It wil always have 2 properties. 3 properties won't be possible:
var people = {
'John': { ... },
'Peter': { ... }
}
And I have the variable var name = 'John'.
Is there a simple way to get the value of property 'Peter' when the value of name is 'John'?
Without hard-coding it with the names John en Peter. So the functionality must get the opposite property of the value in variable name
let name = 'John'; // or whatever
let names = Object.keys(people);
let otherName = names.find(n => n !== name);
people[otherName] // this gives you the value of the other name's property
Object.keys will give you an array of the property names.
filter lets you filter that array.
So:
const name = "John";
const people = {
'John': 1,
'Peter': 1
};
const [result] = Object.keys(people).filter(person => person !== name);
console.log({
result
});
I wrote a simple function, that does this. It takes a key, and an object. It returns the value of the element in the given object by the inverse key of the given key. This will only work if the object only has two keys.
var people = {
'John': { 'b':[3,4] },
'Peter': { 'a':[1,2] }
}
getInverseObjectElem = (key,object) => { // Define function 'getInverseObjectElem'
listOfObjectKeys = Object.keys(object) // Create an array of the object keys
inverseKey = listOfObjectKeys.filter(k => k != key)[0] // filter the list of keys, and get the first key that doesnt match the given key.
return object[inverseKey] // Return the value in the object, by the inverseKey
}
console.log(getInverseObjectElem('John',people))
You could try this:
for (let key in people){
if (key != name) return people[key];
}

Check a key on a JSON object

We are getting JSON string two ways:
"{"phoneNumber":[{"remove":["0099887769"]},{"add":["0099887765"]}]}"
Or
"{"phoneNumber":["0099887765"]}"
We have to convert "{"phoneNumber":[{"remove":["0099887769"]},{"add":["0099887765"]}]}" in "{"phoneNumber":["0099887765"]}" way
Is there any way to write a JavaScript to determine which JSON has "add" key and which one don't have.
When you parse the JSON, you'll have an array with two entries (each objects) if it's the first style, or an array with one entry that's a string. So:
function handle(theJSON) {
let parsed = JSON.parse(theJSON);
if (typeof parsed.phoneNumber[0] === "object") {
parsed.phoneNumber = [parsed.phoneNumber.find(o => o.add).add[0]];
}
console.log(parsed);
}
Live Example:
function handle(theJSON) {
let parsed = JSON.parse(theJSON);
if (typeof parsed.phoneNumber[0] === "object") {
parsed.phoneNumber = [parsed.phoneNumber.find(o => o.add).add[0]];
}
console.log(parsed);
}
handle('{"phoneNumber":[{"remove":["0099887769"]},{"add":["0099887765"]}]}');
handle('{"phoneNumber":["0099887765"]}');
Or if you need an ES5 version:
function handle(theJSON) {
var parsed = JSON.parse(theJSON);
if (typeof parsed.phoneNumber[0] === "object") {
parsed.phoneNumber = [parsed.phoneNumber.find(function(o) { return o.add; }).add[0]];
}
console.log(parsed);
}
You can use some to return true/false if "add" is a property on any object in the array. Here's a general solution:
const json = '{"phoneNumber":[{"remove":["0099887769"]},{"add":["0099887765"]}]}';
const data = JSON.parse(json);
function checkForKey(data, { arrayKey, searchKey }) {
return data[arrayKey].some(obj => obj[searchKey]);
}
const hasAdd = checkForKey(data, {arrayKey: 'phoneNumber', searchKey: 'add' });
console.log(hasAdd);
You can do it by using for..in loop and hasOwnProperty check, finally push only the phoneNumbers with add index. Hope this helps :)
const expected = {'phoneNumber':[]};
let str = '{"phoneNumber":[{"add":["0099844465"],"remove":["0099887769"]},{"add":["0099887765"]}]}';
const st_obj = JSON.parse(str);
for (var k in st_obj['phoneNumber']) {
if (st_obj['phoneNumber'][k].hasOwnProperty('add')) {
expected['phoneNumber'].push(st_obj['phoneNumber'][k]['add']);
}
}
console.log(expected);
use let obj = JSON.parse('{"phoneNumber":[{"remove":["0099887769"]},{"add":["0099887765"]}]}') to convert it to object.
then iterate it and fetch value and push it into new object
just check if add is top level propery
if(obj['add']) {....}
if it is exists then if will be true, if not it will return undefined and if will be false,
if you should check it in array of objects, you can use the same logic with find method from array prototype
phoneNumber.find(obj => obj['add']);
You can check whether the add key exists by converting the JSON into array:
How to convert JSON object to JavaScript array
With that you are able to check if the key exists by checking whether the key is undefined:
obj["phonenumber"]["add"] != undefined

Remove false values in object

The problem that I'm facing is -removing the values in the onject that has the property false
Here is the object
var myObj={105:true,183:false,108:true,106:false}
I'm able to get the values in an array by using the following logic:
Object.keys(myObj) gives ["105","183","108","106"]
But I need a way to remove the values that have the property false and generate as ["105",108"].Can you help me out ?
You have the keys of the object in an array. Run filter over it.
var myObj={105:true,183:false,108:true,106:false};
var result = Object.keys(myObj).filter(function(x) {
return myObj[x] !== false;
});
// result = ["105", "108"]
I've just created a solution to your problem on JSBin: Working Demo
Please find below the code:
var myObj={105:true,183:false,108:true,106:false};
var myArray = [];
function RemoveFalseAndTransformToArray () {
for (var key in myObj) {
if(myObj[key] === false) {
delete myObj[key];
} else {
myArray.push(key);
}
}
}
RemoveFalseAndTransformToArray();
console.log("myObj: ", myObj);
console.log("myArray: ", myArray);
// result = ["105", "108"]
Please, let me know if you have any question.
To remove those properties you can use this algorithm:
for (k in myObj)
{
if (myObj.hasOwnProperty(k) && myObj[k] === false)
{
delete myObj[k];
}
}
If you are just interested in the keys of non-false values, you can use:
var keys = Object.keys(myObj).filter(function (k) {
return myObj[k] !== false;
});
The hasOwnProperty() check is necessary because objects may contain non-user properties (such as prototype) which you really don't want to mess with.
You need to iterate over the object using for...in loop
var myObj={105:true,183:false,108:true,106:false}
for(var key in myObj){
if(myObj.hasOwnProperty(key) && myObj[key] == false){
delete myObj[key];
}
}
console.log(JSON.stringify(myObj)) //{"105":true,"108":true}
console.log(Object.keys(myObj)) //["105", "108"]
ES6 has a one line way to do this, this mutates the original array!
Object.keys(myObj).map(key => !myObj[key] && delete myObj[key])
to avoid this use the spread operator
const filteredObj = [...myObj]
Object.keys(filteredObj).map(key => !filteredObj[key] && delete filteredObj[key])

How to determine if object is in array [duplicate]

This question already has answers here:
How do I check if an array includes a value in JavaScript?
(60 answers)
Closed 29 days ago.
I need to determine if an object already exists in an array in javascript.
eg (dummycode):
var carBrands = [];
var car1 = {name:'ford'};
var car2 = {name:'lexus'};
var car3 = {name:'maserati'};
var car4 = {name:'ford'};
carBrands.push(car1);
carBrands.push(car2);
carBrands.push(car3);
carBrands.push(car4);
now the "carBrands" array contains all instances.
I'm now looking a fast solution to check if an instance of car1, car2, car3 or car4 is already in the carBrands array.
eg:
var contains = carBrands.Contains(car1); //<--- returns bool.
car1 and car4 contain the same data but are different instances they should be tested as not equal.
Do I have add something like a hash to the objects on creation? Or is there a faster way to do this in Javascript.
I am looking for the fastest solution here, if dirty, so it has to be ;) In my app it has to deal with around 10000 instances.
no jquery
Use something like this:
function containsObject(obj, list) {
var i;
for (i = 0; i < list.length; i++) {
if (list[i] === obj) {
return true;
}
}
return false;
}
In this case, containsObject(car4, carBrands) is true. Remove the carBrands.push(car4); call and it will return false instead. If you later expand to using objects to store these other car objects instead of using arrays, you could use something like this instead:
function containsObject(obj, list) {
var x;
for (x in list) {
if (list.hasOwnProperty(x) && list[x] === obj) {
return true;
}
}
return false;
}
This approach will work for arrays too, but when used on arrays it will be a tad slower than the first option.
Why don't you use the indexOf method of javascript arrays?
Check this out: MDN indexOf Arrays
Simply do:
carBrands.indexOf(car1);
It will return you the index (position in the array) of car1. It will return -1 if car1 was not found in the array.
http://jsfiddle.net/Fraximus/r154cd9o
Edit: Note that in the question, the requirements are to check for the same object referenced in the array, and NOT a new object. Even if the new object is identical in content to the object in the array, it is still a different object.
As mentioned in the comments, objects are passed by reference in JS and the same object can exist multiple times in multiple structures.
If you want to create a new object and check if the array contains objects identical to your new one, this answer won't work (Julien's fiddle below), if you want to check for that same object's existence in the array, then this answer will work. Check out the fiddles here and in the comments.
Having been recently bitten by the FP bug reading many wonderful accounts of how neatly the functional paradigm fits with Javascript
I replicate the code for completeness sake and suggest two ways this can be done functionally.
var carBrands = [];
var car1 = {name:'ford'};
var car2 = {name:'lexus'};
var car3 = {name:'maserati'};
var car4 = {name:'ford'};
var car5 = {name:'toyota'};
carBrands.push(car1);
carBrands.push(car2);
carBrands.push(car3);
carBrands.push(car4);
// ES6 approach which uses the includes method (Chrome47+, Firefox43+)
carBrands.includes(car1) // -> true
carBrands.includes(car5) // -> false
If you need to support older browsers use the polyfill, it seems IE9+ and Edge do NOT support it. Located in polyfill section of MSDN page
Alternatively I would like to propose an updated answer to cdhowie
// ES2015 syntax
function containsObject(obj, list) {
return list.some(function(elem) {
return elem === obj
})
}
// or ES6+ syntax with cool fat arrows
function containsObject(obj, list) {
return list.some(elem => elem === obj)
}
try Array.prototype.some()
MDN Array.prototype.some
function isBiggerThan10(element, index, array) {
return element > 10;
}
[2, 5, 8, 1, 4].some(isBiggerThan10); // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true
You could use jQuery's grep method:
$.grep(carBrands, function(obj) { return obj.name == "ford"; });
But as you specify no jQuery, you could just make a derivative of the function. From the source code:
function grepArray( elems, callback, inv ) {
var ret = [];
// Go through the array, only saving the items
// that pass the validator function
for ( var i = 0, length = elems.length; i < length; i++ ) {
if ( !inv !== !callback( elems[ i ], i ) ) {
ret.push( elems[ i ] );
}
}
return ret;
}
grepArray(carBrands, function(obj) { return obj.name == "ford"; });
I used underscore javascript library to tweak this issue.
function containsObject(obj, list) {
var res = _.find(list, function(val){ return _.isEqual(obj, val)});
return (_.isObject(res))? true:false;
}
please refer to underscore.js documentation for the underscore functions used in the above example.
note: This is not a pure javascript solution. Shared for educational purposes.
You can just use the equality operator: ==. Objects are checked by reference by default, so you don't even need to use the === operator.
try this, just make sure you're using the correct variable reference in the place of car1:
var i, car, l = cars.length;
for (i = 0; i < l; i++)
{
if ((car = cars[i]) == car1)
{
break;
}
else car = null;
}
Edit to add:
An array extension was mentioned, so here's the code for it:
Array.prototype.contains = Array.prototype.contains || function(obj)
{
var i, l = this.length;
for (i = 0; i < l; i++)
{
if (this[i] == obj) return true;
}
return false;
};
Note that I'm caching the length value, as the Array's length property is actually an accessor, which is marginally slower than an internal variable.
I would use a generic iterator of property/value over the array. No jQuery required.
arr = [{prop1: 'val1', prop2: 'val2'}, {prop1: 'val3', prop2: 'val4'}];
objectPropInArray(arr, 'prop1', 'val3'); // <-- returns true
function objectPropInArray(list, prop, val) {
if (list.length > 0 ) {
for (i in list) {
if (list[i][prop] === val) {
return true;
}
}
}
return false;
}
You could try sorting the array based on a property, like so:
carBrands = carBrands.sort(function(x,y){
return (x == y) ? 0 : (x > y) ? 1 : -1;
});
Then you can use an iterative routine to check whether
carBrands[Math.floor(carBrands.length/2)]
// change carBrands.length to a var that keeps
// getting divided by 2 until result is the target
// or no valid target exists
is greater or lesser than the target, and so on, which will let you go through the array quickly to find whether the object exists or not.
try this ,
You can use the JavaScript some() method to find out if a JavaScript array contains an object.
<script>
// An array of objects
var persons = [{name: "Harry"}, {name: "Alice"}, {name: "Peter"}];
// Find if the array contains an object by comparing the property value
if(persons.some(person => person.name === "Peter")){
alert("Object found inside the array.");
} else{
alert("Object not found.");
}
</script>
EDIT 05/18/2022
The most simple way using ES6:
const arrayContainsObject = <T extends Record<string, unknown>>(array: T[], object: T) => {
return array.some(item => Object.keys(item).every(key => item[key] === object[key]))
}
Use like so:
const arr = [{
prop1: 'value1',
prop2: 'value2'
}]
const obj1 = {
prop1: 'value1',
prop2: 'value2'
}
const obj2 = {
prop2: 'value2',
prop1: 'value1'
}
const obj3 = {
prop0: 'value0',
prop1: 'value1'
}
arrayContainsObject(arr, obj1) // true
arrayContainsObject(arr, obj2) // true, even when props are arranged in different order
arrayContainsObject(arr, obj3) // false
Previous answer, don't use (because the order of props in an object needs to be identical)
const arr = [{
prop: 'value'
}]
const obj = {
prop: 'value'
}
arr.some((e) => Object.entries(e).toString() === Object.entries(obj).toString()) // true
i know this is an old post, but i wanted to provide a JQuery plugin version and my code.
// Find the first occurrence of object in list, Similar to $.grep, but stops searching
function findFirst(a,b){
var i; for (i = 0; i < a.length; ++i) { if (b(a[i], i)) return a[i]; } return undefined;
}
usage:
var product = $.findFirst(arrProducts, function(p) { return p.id == 10 });
This function is to check for a unique field.
Arg 1: the array with selected data
Arg 2: key to check
Arg 3: value that must be "validated"
function objectUnique( array, field, value )
{
var unique = true;
array.forEach(function ( entry )
{
if ( entry[field] == value )
{
unique = false;
}
});
return unique;
}
you can use Array.find().
in your case is going to look like this
carBrands.find(function(car){
let result = car.name === 'ford'
if (result == null){
return false;
} else {
return true
}
});
if car is not null it will return the javaScript Object which contains the string 'ford'
The issue with many of the answers here is that they will NOT find an object in an array that is equal to another object. They will only search for an EXISTING object that has a pointer to it in an array.
Quick fix using lodash to see if ANY equal object is in an array:
import _ from 'lodash';
_.find(carBrands, car1); //returns object if true, undefined if false
Working Plunker using this method: https://plnkr.co/edit/y2YX9o7zkQa2r7lJ
if its possible to use es6
carBrands.filter(carBrand => carBrand.name === carX.name).length > 0
if it's true there is a similarity
You can convert both the JSON objects to string and simply check if the bigger json contains the smaller json.
console.log(JSON.stringify(carBrands).includes(JSON.stringify(car1))); // true
console.log(JSON.stringify(carBrands).includes(JSON.stringify(car5))); // false
You could also a the findIndex
var carBrands = [];
var car1 = {name:'ford'};
var car2 = {name:'lexus'};
carBrands.push(car1);
if (carBrands.findIndex(f => f.name === car1.name) === -1) {
console.log('not contain')
} else {
console.log('contain')
}
if (carBrands.findIndex(f => f.name === car2.name) === -1) {
console.log('not contain')
} else {
console.log('contain')
}

Categories

Resources