I have an object like
let obj = {
1: true,
2:false,
3:true
}
How can i return the object key wherever the object value is false, for example, in the case above, only 2 should be returned
I tried Object.values(obj).filter(value => !value) but it only returns false
You are using filter() on Object.values() this way you will not have any way to access the corresponding key
You can use filter() on Object.keys() and check if value at that key is truthy.
let obj = {
1: true,
2:false,
3:true
}
const res = Object.keys(obj).filter(k => !obj[k]);
console.log(res)
Actually, came up with
Object.entries(obj).filter(([key, value]) => !value).map(([key, value]) => key);
which returns what I need.
Related
I'm trying to convert the methods part of an Express Router into a one-dimensional array of uppercase string words, so this:
layer.route.methods: { get: true, post: true }
into:
methods: ["GET", "POST"]
This is what I came up with, but isn't there a more subtle way?
const methods = [];
!layer.route.methods.get || methods.push('GET');
!layer.route.methods.post || methods.push('POST');
This can be achieved with a combination of filter (to get only the methods with true) and map (to capitalize).
const methods = { get: true, post: true };
const result = Object.keys(methods).filter(method => methods[method]).map(method => method.toUpperCase());
console.log(result);
Turn down object to an array by using Object.keys(object) and then use loop either for or map to iterate and check if item exist in that converted array convert then to uppercase using item.toUpperCase()
One of the ways is to use reducer, to filter and modify values in one iteration.
const inputObject = { get: true, post: true };
const methods = Object.entries(inputObject).reduce(
(accumulator, [key, value]) => {
if (value) accumulator.push(key.toUpperCase());
return accumulator;
},
[]
);
console.log(methods);
I have this Object:
{
"data": {
"success": true,
"historical": true,
"date": "2022-01-01",
"base": "MXN",
"rates": {
"COFFEE": 0.02158734144632395,
"CORN": 0.008232645172711363,
"COTTON": 0.04320921676820366,
"SOYBEAN": 0.0036714622235960175,
"SUGAR": 0.25680398615582695,
"WHEAT": 0.00017592643558262669
},
"unit": "per bushel"
}
}
And I want to iterate over "rates" to replace the values of each key with 1 / value
I tried with: (prueba is the Object name)
Object.values(this.prueba.data.rates).forEach((val) => {
console.log(val)
val = 1 / val;
console.log(val)
})
But how to replace those values or how can I saved them in another array or Object
Your code doesn't work because the change you made to val is only reflected within the scope of the callback.
You should instead loop through each property and set its value.
const obj={data:{success:!0,historical:!0,date:"2022-01-01",base:"MXN",rates:{COFFEE:.02158734144632395,CORN:.008232645172711363,COTTON:.04320921676820366,SOYBEAN:.0036714622235960175,SUGAR:.25680398615582695,WHEAT:.00017592643558262669},unit:"per bushel"}};
let r = obj.data.rates;
Object.keys(r).forEach(e => r[e] = 1 / r[e])
console.log(obj)
If you're using Typescript it's necessary to declare the object like so:
const obj: {[key: string]: any} = ...
You can iterate over Object.entries (or Object.keys) and replace the value for each key.
let obj={data:{success:!0,historical:!0,date:"2022-01-01",base:"MXN",rates:{COFFEE:.02158734144632395,CORN:.008232645172711363,COTTON:.04320921676820366,SOYBEAN:.0036714622235960175,SUGAR:.25680398615582695,WHEAT:.00017592643558262669},unit:"per bushel"}};
Object.entries(obj.data.rates).forEach(([k, v]) => obj.data.rates[k] = 1 / v);
console.log(obj);
I think it will be cleaner to write it explicitly using for loops:
let obj = {} //original object stated in question
let obj2 = Object.create(null);//DON'T just use {}, see below
for(let productName in obj.data.rates){
let inverse = 1/obj.data.rates[productName];
//to edit the object directly
obj.data.rates[productName] = inverse;
//to add to another object
obj2[productName] = inverse;
}
The difference between {} and Object.create(null) can be found here
You can combine Object.entries(), Array#forEach() and Destructuring assignment
Code:
const obj = {data:{success:0,historical:0,date:"2022-01-01",base:"MXN",rates:{COFFEE:.02158734144632395,CORN:.008232645172711363,COTTON:.04320921676820366,SOYBEAN:.0036714622235960175,SUGAR:.25680398615582695,WHEAT:.00017592643558262669},unit:"per bushel"}}
const replaceValue = ({ data: { rates: r }}) =>
Object
.entries(r)
.forEach(([k, v]) => r[k] = 1 / v)
replaceValue(obj)
console.log(obj)
I have an array :
[
"2022-05-20",
"2022- 06-22",
"2022-06-20"
]
and I want to produce an object like this:
{
'2022-05-20': {disabled:true},
'2022-06-22': {disabled: true},
'2022-06-20': {disabled: true},
}
I tried using a for loop but it kept producing errors. Is this possible with javascript?
You can use Array#reduce as in the following demo. You can also use Array#map but you would have to use Object.fromEntries as well.
const input = [ "2022-05-20", "2022- 06-22", "2022-06-20" ],
output = input.reduce(
(prev,cur) =>
({...prev,[cur]:{disabled:true}}), {}
);
console.log( output );
USING Array#map ...
Here is how you can use Array#map:
const input = [ "2022-05-20", "2022- 06-22", "2022-06-20" ],
output = Object.fromEntries(
input.map(date => [date, {disabled:true}])
);
console.log( output );
Can do it:
let dates = [
"2022-05-20",
"2022- 06-22",
"2022-06-20"
];
let newObj = Object.assign(...dates.map(key => ({[key]: {disabled: true}})));
console.log(newObj)
This might get the job done.
const yourArray = ["2022-05-20", "2022-06-22", "2022-06-20"];
const obj = {};
for(const x of yourArray) obj[String(x)] = { disabled: true };
console.log(obj); // :)
Create the variable obj that is going to save the produced object you want. Iterating throw your array and using a string parsed version of the value in the current iteration (parsing just in case, if you already know the array is made of strings, this is kinda unnecessary) to save it as a key on the new object, also assigning to that key, the value { disabled: true }.
Here is a one liner solution:
let res = data.reduce((acc, curr) =>(acc[curr] = {disabled: true}, acc), {});
This question already has answers here:
Remove blank attributes from an Object in Javascript
(53 answers)
Closed 2 years ago.
Is there a better way to accomplish this in Javascript?
const data: any = {};
if (values.email) data.email = values.email;
if (values.password) data.password = values.password;
if (values.username) data.username = values.username;
I don't want the data object to have the properties for the undefined or falsy values.
You could put the potential properties in an array and then .filter() out any which values[prop] has a fasly value for. Then you can .map() each key to an array of [key, value] pairs, and use Object.fromEntries() to build the data object for you:
const values = {
email: 'abc',
username: 'xyz'
};
const props = ['email', 'password', 'username'];
const data = Object.fromEntries(
props.filter(prop => values[prop]).map(prop => [prop, values[prop]])
);
console.log(data);
If you can't support Object.fromEntries(), you could consider using Object.assign(), and then mapping to an array of objects which you then spread into Object.assign():
const values = {
email: 'abc',
username: 'xyz'
};
const props = ['email', 'password', 'username'];
const data = Object.assign({},
...props.filter(prop => values[prop]).map(prop => ({[prop]: values[prop]}))
);
console.log(data);
You can do something along these lines:
const obj1 = {
prop1: true,
prop2: false,
prop3: 4,
}
const obj2 = Object.entries(obj1).reduce((result, [key, value]) => {
if (value) {
result[key] = value
}
return result
}, {})
console.log(obj2)
This simple function will do it, if you want to copy over all properties that don't have a false-y value. If you only want a fixed list, look at the answer from Nick Parsons.
const copyNonNil = (obj) =>
Object .fromEntries (Object .entries (obj) .filter(([k, v]) => v))
const values = {
email: 'foo#bar.baz',
username: 'foobar',
password: '',
another: false
}
console .log (copyNonNil (values))
It's easy to shim Object .fromEntries if you don't have it available. See the answer from theDude, which uses a reduce that serves in the same role.
You could use Object.entries to iterate over the properties of values and perform the true/false check in that to make this more flexible:
for(const [key, value] of Object.entries(values)){
if(values[key]) data[key] = value;
}
This would give you only the truthy values in data for a values object of any size.
Is there some elegant way of filtering out falsey properties from this object with lodash/underscore? Similar to how _.compact(array) removes falsey elements from arrays
so from
{
propA: true,
propB: true,
propC: false,
propD: true,
}
returning
{
propA: true,
propB: true,
propD: true,
}
Here are two vanilla javascript options:
A.: Iterate over the object's keys and delete those having a falsey value.
var obj = {
propA: true,
propB: true,
propC: false,
propD: true,
};
Object.keys(obj).forEach(key => {
if (!obj[key]) delete obj[key];
});
console.log(obj);
See Object.keys() and Array.prototype.forEach()
B.: Iterate over the object's keys and add truthy values to a new object.
var obj = {
propA: true,
propB: true,
propC: false,
propD: true,
};
var filteredObj = Object.keys(obj).reduce((p, c) => {
if (obj[c]) p[c] = obj[c];
return p;
}, {});
console.log(filteredObj);
See Object.keys() and Array.prototype.reduce()
Lodash 4.0
Lodash 4.0 has _.pick, which takes an array of properties, and _.pickBy which takes a function as an argument and returns an object only containing the keys for which that function returns truthy which is what we want here, so it'd be:
filtered = _.pickBy(obj, function(value, key) {return value;})
Or, since _.pickBy defaults to using _.identity as it's second argument, (and that's essentially what we've written above,) it can just be written as:
filtered = _.pickBy(obj);
Underscore or Lodash prior to version 4.0
In underscore and old versions of lodash, there's just a single _.pick, which has both behaviors of _.pick and _.pickWith from v4. So you can do:
filtered = _.pick(obj, function(value, key) {return value;})
Or more succinctly:
filtered = _.pick(obj, _.identity)
Unfortunately I cannot direclty comment on the posts above yet, so I create this extra post.
Since Lodash v4 the functionality described above has been moved to _.pickBy. With _.identity as default you could also change your code to:
var filtered = _.pickBy(obj);
See this JSBin for a working example.
As partial mentioned in a comment, ES6 provided Object.entries() and in 2019 Object.fromEntries().
Allowing:
Object.fromEntries(Object.entries(obj).filter(([key, value]) => ...))
Ex:
const obj = {
a: 12,
b: 123,
};
const filteredObj = Object.fromEntries(
Object.entries(obj).filter(
([_, value]) => value > 100
)
);
console.log(filteredObj);
// {b: 123}
If you're using lodash, I'd recommend something like this:
var object = {
propA: true,
propB: true,
propC: false,
propD: true,
};
_.pick(object, _.identity);
// →
// {
// propA: true,
// propB: true,
// propD: true
// }
The pick() function generates a new object that includes properties that the callback returns truthy for. So we can just use the identity() function as the callback, since it'll just return each property value.
From lodash 4, we can use pickBy() to get only the value equal to true.
const active = _.keys(_.pickBy(object));
let temp = {
propA: true,
propB: true,
propC: false,
propD: true,
}
let obj = {}
for(x in temp){
if(temp[x] == true){
obj[x] = temp[x]
}
}
console.log(obj)
Using for-in loop we can achieve it something like this.
Another approach
const objFilter = (obj, condition) => {
let newObj = {}
for (const [key, value] of Object.entries(obj)) {
if (condition(value)) {
newObj = { ...newObj, [key]: value }
}
}
return newObj
}
Fire like this:
const newData = objFilter(oldData, (value) => value.marked === false)