How to change value of object attribute on some condition - javascript

I have an object like this.
Obj : {
USA : true
NZ : false,
Canada : true,
Japan : false,
China : true
Ind : false,
}
In my function I am getting countery.name = IND so on this condition how can I change the flag of respective country.
What I am trying on this here is
var countryName = countery.name // Getting some value here.
Object.keys(obj).map(function(i) {
/*if(countryName == obj.countryName){ // something missing here
obj.countryName.value
}*/
});

change to true or false. Opsite to current value
The solution using Object.keys function:
var Obj = {USA : true,NZ : false,Canada : true,Japan : false,China : true,Ind : false},
keys = Object.keys(Obj),
len = keys.length,
countryName = 'IND';
while (len--) {
if (keys[len].toLowerCase() == countryName.toLowerCase()) {
Obj[keys[len]] = !Obj[keys[len]];
break; // avoiding redundant iterations
}
}
console.log(Obj);

Get the properties of the object via Object.keys() and then use some() to iterate over properties toLowerCase() function to compare property and the country name. In if statement use return true to break the loop if the key is found.
var obj = {
USA: true,
NZ: false,
Canada: true,
Japan: false,
China: true,
Ind: false
};
var country = {
name: 'IND'
};
Object.keys(obj).some(key => {
if(key.toLowerCase() === country.name.toLowerCase()){
obj[key] = !obj[key];
return true;
}
});
console.log(obj);

You could use Array#some and exit the loop if found.
var obj = { USA: true, NZ: false, Canada: true, Japan: false, China: true, Ind: false },
countryName = 'IND';
Object.keys(obj).some(function (k) {
if (k.toLowerCase() === countryName.toLowerCase()) {
obj[k] = !obj[k];
return true;
}
});
console.log(obj);

You can change the object's property like obj[countryName] = !obj[countryName].value when the condition passes.
obj = {USA:true, NZ: false, Canada:true,Japan:false,China:true,Ind:false};
var countryName = 'Ind';
console.log("Before changing the flag:");
console.log(obj);
Object.keys(obj).map(function(i){
if (countryName == i)
obj[countryName] = !obj[countryName].value;
});
console.log("After changing the flag:");
console.log(obj);

Related

extract object by property prefix

I tried to loop through a huge list of properties in object, but failed to extract properties that has the same prefix, I can't use object deletefunction because the list is huge, where is my mistake?
const a = {
obj_abc: true,
obj_def: false,
hello_123: true,
hello_456: 'another value'
};
let b = {};
for(k in a){
const [key] = k.split('_');
if(key === 'hello') {
b = {...b[key], [key]:a[k]} //the problem is here, it gave me only hello_456: 'another value'
}
}
console.log(b);
Try using bracket notation
const a = {
obj_abc: true,
obj_def: false,
hello_123: true,
hello_456: 'another value'
};
let b = {};
for (k in a) {
const [key] = k.split('_');
if (key === 'hello') {
b[k] = a[k];
}
}
console.log(b);
Using startsWith()
const a = {
obj_abc: true,
obj_def: false,
hello_123: true,
hello_456: 'another value'
};
let b = {};
for (k in a) {
if (k.startsWith('hello_')) {
b[k] = a[k];
}
}
console.log(b);
Your key is hello for both hello_123 and hello_456, hence its overriding the old entry for hello key. you need unique keys. eg below.
const a = {
obj_abc: true,
obj_def: false,
hello_123: true,
hello_456: 'another value'
};
let b = {};
for(k in a){
const [key] = k.split('_');
if(key === 'hello') {
//key is hello for both hello_123 and hello_456, hence its overriding
b[k] = a[k] //the problem is here, it gave me only hello_456: 'another value'
}
}
console.log(b);
Try this
const a = {
obj_abc: 123,
obj_def: 456,
hello_123: 123,
hello_456: 456
};
// filter out the keys that start with hello
var keys = Object.keys(a).filter(function(k) {
return k.indexOf("hello") === 0;
});
//to convert an array of filtered keys into an object of key-value pairs
var res = keys.reduce(function(matched, k) {
matched[k] = a[k];
return matched;
}, {});
console.log(res);
You can use entries, reduce for clean code. Same time you can create map of all key, later good to extract. See the example 2.
// Example 1
const a = {
obj_abc: true,
obj_def: false,
hello_123: true,
hello_456: 'another value'
};
const result = Object.entries(a).reduce((map, [key, value]) => {
if (key.indexOf("hello_") === 0) map[key] = value
return map
}, {})
console.log(result);
// To collect all in once
// Example 2
const result2 = Object.entries(a).reduce((map, [key, value]) => {
const [k] = key.split("_")
if(!map[k]) map[k] = {}
map[k][key] = value
return map
}, {})
console.log(result2); // { obj: { obj_abc: true, obj_def: false }, hello: { hello_123: true, hello_456: 'another value' } }
console.log(result2["hello"]); // { hello_123: true, hello_456: 'another value' }
console.log(result2["obj"]); // { obj_abc: true, obj_def: false }
Please find my answer.
const a = {
obj_abc: true,
obj_def: false,
hello_123: true,
hello_456: "another value"
};
let b = {};
for (key in a) {
let [text] = key.split("_");
if (!(text in b)) {
b[text] = { [key]: a[key] };
}
else {
Object.assign(b[text], { [key]: a[key] });
}
}
console.log(b);
OUTPUT
{
"obj": {
"obj_abc": true,
"obj_def": false
},
"hello": {
"hello_123": true,
"hello_456": "another value"
}
}

Map through an inner array of an Object

I have this object:
let arr = [{
id : 1,
usr : 'pimba',
xyz: null
},
{
id : 2,
usr : 'aloha',
xyz: {
xyz_id: 2
}
},
{
id : 3,
age : 'pruu',
xyz: null
}];
As you can notice, sometimes xyz is null and sometimes it's not.
I need to recognize whether it is null or not, so I can read it.
I was trying to use map() function but I can't set some sort of filter to only execute the annonymous function when it is NOT null.
I managed to do something like this:
let result = Object.values(arr).map(function(row){
if(row['xyz'] != null) {
console.log(row['xyz_id']);
}
});
what If I want a new array containing ONLY xyz_id ? Is there a shorter version ?
Second case:
There are more than 1 value inside xyz and it's NOT "named".
let arr = [{
id : 1,
usr : 'pimba',
xyz: null
},
{
id : 2,
usr : 'aloha',
xyz: {
xyz_id: {"value1Here", "Value2Here"}
}
},
{
id : 3,
age : 'pruu',
xyz: null
}];
It seems you want to map the array only for the elements that have not-null xyz property. One option is using both .filter and .map methods. Another option is using the .reduce method:
let result = arr.reduce(function(ret, row) {
// assuming `xyz` can be only `null` or an object
if ( row.xyz !== null ) {
ret.push(row.xyz.xyz_id);
}
return ret;
}, []);
You might want to look at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
const notNull = arr.filter(elm => elm.xyz !== null);
var a = {one: 1, two: null, three: 3, four: true}
var y = []
let scan = (obj) => {
Object.keys(obj).forEach(x => {
if (obj[x] === null) {
console.log('Its null')
} else {
// Extend here to datatypes
y.push(obj[x])
}
});
}
scan(a)
console.log(y)

Why my 2 object deep comparison is failing?

I am trying to compare 2 objects using deep comparison and while comparison i want to ignore some properties.
My comparison is successful when I have those ignore properties on both the side of object.
But I am getting problem when I have 1 property missing in 2nd object which I want to ignore.
In my objA and objB, I want to ignore isParent and location property but as I don't have location property in objB, my object comparison is failing.
But I don't understand why I am getting false as I have specified location property to ignore.
var objA = {
isParent: true,
foo: {
location: "abc",
bar: "foobar"
}
};
var objB = {
isParent: false,
foo: {
bar: "foobar"
}
};
var comparator = function(left, right, key) {
if (key === 'isParent' || key === 'location') return true;//ignore isParent and location property while comparing 2 object
else return undefined;
}
var isEqual = _.isEqualWith(objA, objB, comparator);
console.log(isEqual); // true
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
Use the omit function to ignore unwanted properties then compare
var objA = {
isParent: true,
foo: {
location: "abc",
bar: "foobar"
}
};
var objB = {
isParent: false,
foo: {
bar: "foobar"
}
};
var isEqual = _.isEqual(
_.omit(objA, ['isParent', 'foo.location']),
_.omit(objB, ['isParent', 'foo.location'])
);
console.log(isEqual); // true
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
You can write your own compare function:
Logic:
Create a function that takes 2 objects that will be compared and an array(ignoreKeys) of keys that are to be ignored.
Get all keys from both object, merge them and then filter them into a new variable (say keys).
If the current key exists in keys, ignore it.
If the current key exists in ignoreKeys, ignore it
Else push it.
Now loop over these keys and check for comparison:
If current value is of type 'object', use recursion and start the process again.
Else, compare the values and return the comparison.
Since this has to be done for all the keys in keys, you can use Array.every.
Sample
function compareObject(obj1, obj2, ignoreProps){
var temp = Object.keys(obj1).concat(Object.keys(obj2)).sort();
var keys = temp.reduce(function(p,c) {
if(p.indexOf(c) < 0 && ignoreProps.indexOf(c) < 0) {
p.push(c);
}
return p;
}, []);
return keys.every(function(key){
var t1 = typeof(obj1[key])
var t2 = typeof(obj2[key])
if(t1 === t1) {
switch(t1) {
case 'object':
if(obj1[key] !== null && obj2[key] !== null)
return compareObject(obj1[key], obj2[key], ignoreProps);
else
return obj1[key] === obj2[key];
default: return obj1[key] === obj2[key];
}
}
})
}
var objA = {
isParent: true,
foo: {
location: "abc",
bar: "foobar",
test: {
location: 'bla',
test1: {
location: 'bla bla',
value: null
}
}
}
};
var objB = {
isParent: false,
foo: {
bar: "foobar",
test: {
location: 'new',
test1: {
location: 'new new',
value: null
}
}
}
};
var ignoreProperties = ['isParent', 'location'];
console.log(compareObject(objA, objB, ignoreProperties));
You could take all keys of the given objects and iterate and check if either
is a key of a no value check (ignore),
has same values or
both values are truthy and objects and the call of check returns a truthy value.
The keys of the properties to ignore are collected in an object.
function check(o, p) {
var keys = [...new Set(Object.keys(o).concat(Object.keys(p)))];
return keys.every(k => noValueCheck[k]
|| o[k] === p[k]
|| o[k] && p[k] && typeof o[k] === 'object' && typeof p[k] === 'object' && check(o[k], p[k])
);
}
var noValueCheck = { isParent: true, location: true },
objA = { isParent: true, foo: { location: "abc", bar: "foobar" } },
objB = { isParent: false, foo: { bar: "foobar" } };
console.log(check(objA, objB));

return non array in using map

I used map to loop but it returned an array, not sure I should use something else like forEach. I have this initial object.
data.discounts: [{
days: 3,
is_enable: true
},{
days: 10,
is_enable: false
}]
Then I do the checking on is_enable
const newObj = {
"disableDiscount_3": !isEmpty(data.discounts) ? (data.discounts.map(obj => obj.days === 3 && obj.is_enable === true ? true : false)) : ''
}
then it became
newObj.disableDiscount_3 = [{
true,
false,
false,
false
}]
What I want is actually just true or false like: newObj.disableDiscount_3 = true What should I do?
map() method is not meant to be used for that, instead you can use some() that will check if specified object exists and return true/false.
var discounts = [{
days: 3,
is_enable: true
}, {
days: 10,
is_enable: false
}]
var check = discounts.some(e => e.days == 3 && e.is_enable === true);
console.log(check)
To first find specific object you can use find() method and if the object is found then you can take some property.
var data = {
discounts: [{
days: 3,
is_enable: true,
value: 123
}, {
days: 10,
is_enable: false
}]
}
var obj = {
"discount_3": (function() {
var check = data.discounts.find(e => e.days == 3 && e.is_enable === true)
return check ? check.value : ''
})()
}
console.log(obj)

How to find all objects with a false value within an array?

What is the correct way to get all objectkeys with a false value in an array like this in Javascript:
[
{ unknownkey1 : false },
{ unknownkey2 : true },
{ unknownkey3 : false },
{ unknownkey4 : true },
{ unknownkey5 : false },
{ unknownkey6 : true }
]
Result should be an array containg all keys with a false value.
What I want is a cleaner solution for this:
for(var i = 0; i < results.length; i++ ){
for ( key in results[i] ) {
if ( results[i].hasOwnProperty( key ) && results[i][key] === false ){
console.log( key );
}
}
}
If the value is not false it contains another object. But they are not needed and I would prefere a way that ignores the child objects if possible.
You want to iterate through the array, and then iterate through each key in each of those objects, then store those false keys in another array. Pretty straightforward.
var data = [
{ unknownkey1 : false },
{ unknownkey2 : true },
{ unknownkey3 : false },
{ unknownkey4 : true },
{ unknownkey5 : false },
{ unknownkey6 : true }
];
var keys = [];
data.forEach(function(object) {
for (var key in object) {
if (object[key] === false) keys.push(key);
}
});
var arr=[
{ unknownkey1 : false },
{ unknownkey2 : true },
{ unknownkey3 : false },
{ unknownkey4 : true },
{ unknownkey5 : false },
{ unknownkey6 : true }
]
// You can return a key for false values and nothing for true,
// then filter out the empty indexes:
var falsies= arr.map(function(itm){
return itm[Object.keys(itm)[0]]==false? Object.keys(itm)[0]:''}).
filter(Boolean);
/* returned value: (Array)
unknownkey1,unknownkey3,unknownkey5
*/

Categories

Resources