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])
Related
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
I am trying to compare json_str1 and json_str2, here it should return true as all elements in json_str1 are present in json_str2.
For now I am doing this the long way like this
json_str1 = '{"0":"a","1":"b","2":"c"}';
json_str2 = '{"0":"c","1":"b","2":"a"}';
json_obj1 = $.parseJSON(json_str1);
json_obj2 = $.parseJSON(json_str2);
arr1 = $.map(json_obj1, function(el) { return el });
arr2 = $.map(json_obj2, function(el) { return el });
if($(arr1).not(arr2).length === 0 && $(arr2).not(arr1).length === 0)
alert("equal");
else
alert("not equal");
How could I make it short and simple, without converting the objects into an array ?
https://jsfiddle.net/kq9gtdr0/
Use the following code:
Object.keys(json_obj1) . every(k1 =>
Object.keys(json_obj2) . some(k2 =>
json_obj1[k1] === json_obj2[k2]
)
);
In English:
Every key k1 in json_obj1 satisfies the condition that some key k2 in json_obj2 satisifies the condition that the value of json_obj1 with key k1 is equal to the value of json_obj2 with key k2.
Or in more conversational English:
Every value in the first object matches some value in the second.
Using lodash
var _ = require('lodash');
function compareValues(jstr1, jstr2) {
return _.isEqual(_.valuesIn(JSON.parse(jstr1)).sort(), _.valuesIn(JSON.parse(jstr2)).sort());
}
json_str1 = '{"0":"a","1":"b","2":"c"}';
json_str2 = '{"0":"c","1":"b","2":"a"}';
console.log(compareValues(json_str1, json_str2));
There is short and easy accurate way to this.
You can use a third party but extremely popular utility library called Lodash. Chaining functions you can check for equality.
First parse both JSON into objects
Then use _.values() to extract the values of all keys of each into separate arrays
Find difference of two arrays. If its an empty array then both of them are equal.
You can chain all the steps into one statement like:
_.isEmpty(_.difference(_.values(json_obj1), _.values(json_obj2)))
Example: https://jsfiddle.net/kq9gtdr0/4/
For more information:
https://lodash.com/docs#values
https://lodash.com/docs#difference
https://lodash.com/docs#isEmpty
You can include the library from CDN(https://cdn.jsdelivr.net/lodash/4.5.1/lodash.min.js) or download and use it as normal script. Lodash offers plenty of useful utility functions that makes JS programming a lot easier. You better try it out.
If you prefer using libraries, then you could use underscore isMatch
_.isMatch(object, properties)
Tells you if the keys and values in properties are contained in
object.
Extending the awesome answer by #user663031, in case you need to do deep comparison, here's code that works:
export function objectOneInsideObjectTwo(jsonObj1: any, jsonObj2: any): boolean {
return Object.keys(jsonObj1).every((k1) => {
if (parseType(jsonObj1[k1]) === 'dict') {
return objectOneInsideObjectTwo(jsonObj1[k1], jsonObj2[k1]);
}
if (parseType(jsonObj1[k1]) === 'array') {
const results: boolean[] = [];
jsonObj1[k1].forEach((o: any, i: number) => {
if (parseType(o) === 'dict') {
results.push(objectOneInsideObjectTwo(o, jsonObj2[k1][i]));
} else {
results.push(o === jsonObj2[k1][i]);
}
});
return results.every((r) => r);
}
return Object.keys(jsonObj2).some((k2) => jsonObj1[k1] === jsonObj2[k2]);
});
}
export function parseType<T>(v: T): string {
if (v === null || v === undefined) {
return 'null';
}
if (typeof v === 'object') {
if (v instanceof Array) {
return 'array';
}
if (v instanceof Date) {
return 'date';
}
return 'dict';
}
return typeof v;
}
You can try this
var json_str1 = {"0":"a","1":"b","2":"c"};
var json_str2 = {"0":"c","1":"b","2":"a"};
var flag = 1;
if(Object.keys(json_str1).length == Object.keys(json_str2).length){
Object.keys(json_str1).forEach(function(x){
if(!json_str2.hasOwnProperty(x) || json_str2[x] != json_str1[x]){
flag = 0;
return;
}
});
}
if(flag)
alert('equal');
else
alert('Not Equal');
If you want to find out if both Objects have the same keys there is no way to do this without at least converting the keys of both Objects to an array with Object.keys or looping through both Objects!
The reason is simple: It's clear that you have to compare the number of keys of both Objects and the only way to do this is by looping through all properties or Object.keys.
So I think the shortest way to do this is:
json_obj1 = JSON.parse('{"0":"a","1":"b","2":"c"}');
json_obj2 = JSON.parse('{"0":"c","1":"b","2":"a"}');
keys_1 = Object.keys(json_obj1);
keys_2 = Object.keys(json_obj2);
if(keys_1.length === keys_2.length && keys_1.every(key => keys_2.indexOf(key) >= 0)) {
alert('equal')
} else {
alert('not equal')
}
If you only want to check if all keys from json1 are present in json2 you can do:
json_obj1 = JSON.parse('{"0":"a","1":"b","2":"c"}');
json_obj2 = JSON.parse('{"0":"c","1":"b","2":"a"}');
if(Object.keys(json_obj1).every(key => key in json_obj2)) {
alert('equal');
} else {
alert('not equal');
}
In your question and comments you indicate you are only looking to verify that "all elements in json_str1 are present in json_str2". Your example code doesn't just do that, it checks for the complete equality of keys by testing if all the keys (not values) in the first object are in the second object AND all the keys in the second object are in the first object. By looking at your code, i assume that when you say "elements" you mean keys.
All that aside, this might help:
// Your first few lines of code
json_str1 = '{"0":"a","1":"b","2":"c"}';
json_str2 = '{"0":"c","1":"b","2":"a"}';
json_obj1 = $.parseJSON(json_str1);
json_obj2 = $.parseJSON(json_str2);
// My new code
var values1 = Object.keys(json_obj1).map(key => json_obj1[key]);
var values2 = Object.keys(json_obj2).map(key => json_obj2[key]);
// Check if every key in the first object is in the second object.
values1.every(k1 => values2.indexOf(k1) >= 0);
// OR
// Check for equality of keys by checking both directions.
values1.every(k1 => values2.indexOf(k1) >= 0) && values2.every(k2 => values1.indexOf(k2) >= 0);
That's 2 lines to get the keys, and one line to check. You only need one of those two checks.
Is there a more efficient way to loop through structure like following than doing for() for every level there is ?
[{a:foo,b:[{a:bar},{a:bar}]},{a:bar,b:[]},...]
I need to filter out all the items which property a contains certain data and if it has property b with some elements then loop through those also.
I was thinking of using filter method, but can't seem to figure how to use it efficiently.
guess, I am late, but still, I would do it like...
function filter(obj){
if(obj.constructor === Array){
var arry = [];
obj.forEach(function(item){
var tmp = filter(obj);
if(tmp) arrypush(tmp);
});
return arry;
}
if(obj.a && obj.a.contains('ignore')) // modify this to your filter condition
return;
if(!ob.b || !obj.b.constructor === Array)
return obj;
var newObj={};
Object.keys(obj).forEach(function(key){
newObj[key] = obj[key];
});
newObj.b = filter(obj.b);
return newObj;
}
Welcome to lodash and its collection of awesome methods.
var collection = [{a:foo,b:[{a:bar},{a:bar}]},{a:bar,b:[]},...];
var filteredCollection = _.chain(collection)
.flattenDeep()
.filter(function(item) { return item.a === 'foo'; });
This is not working code per say, you will need to do some of the work to make the loop go through each piece to flatten them individually, I just give you the tools to do the job easier.
Lets say I have javascript objects like this one:
var obj = {
'addr:housenumber': '7',
'addr:street': 'Frauenplan',
'owner': 'Knaut, Kaufmann'
}
How can I check if the object has a property name that starts with addr? I’d imagine something along the lines of the following should be possible:
if (e.data[addr*].length) {
I tried RegExp and .match() to no avail.
You can check it against the Object's keys using Array.some which returns a bool.
if(Object.keys(obj).some(function(k){ return ~k.indexOf("addr") })){
// it has addr property
}
You could also use Array.filter and check it's length. But Array.some is more apt here.
You can use the Object.keys function to get an array of keys and then use the filter method to select only keys beginning with "addr".
var propertyNames = Object.keys({
"addr:housenumber": "7",
"addr:street": "Frauenplan",
"owner": "Knaut, Kaufmann"
}).filter(function (propertyName) {
return propertyName.indexOf("addr") === 0;
});
// ==> ["addr:housenumber", "addr:street"];
This gives you existence (propertyNames.length > 0) and the specific names of the keys, but if you just need to test for existence you can just replace filter with some.
Obj = {address: 'ok', x:5}
Object.keys(obj).some(function(prop){
return ~prop.indexOf('add')
}) //true
You can check this also with startsWith():
Object.keys(obj).some(i => { return i.startsWith('addr') })
Try this:
var myObject = {
'prop1': 'value1',
'xxxxx': 'value2'
};
var stringToCheck = 'addr';
for(var propertyName in myObject) {
var x = propertyName.substr(0, stringToCheck.length - 1);
if(x == stringToCheck) {
return true;
}
}
I don't think "Querying" a object properties is possible. You would have to loop through the properties individually and determine if they match. something like this...
function findProp(e, prop)
{
for(var o in e.data){
if(o.substr(0, prop.length)==prop) //<- you could try the regex or match operation here
return true;
}
return false;
}
alert(findProp({data:{addr:{street:"a", sub:"b"}}}, 'addr'));
You can then process the property if it findProp returns true...
You can write a function
function check(model) {
var keys = [];
for (key in model) {
if(key.indexOf("addr") > -1)
keys.push(key);
}
return keys;
}
Why not just
var foo = {'bar':'funtimes'};
if (foo.bar.includes('fun')) {
console.log('match');
}
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')
}