I Have the following object:
var config = {
apps: false,
transfers: false,
approvals: true
};
I want to know how I can use Lodash to go through each of the keys within the config object and find out which key has the first occurrence of value true. In the example above, I expect the output to be approvals. If the value for transfers was true, I expect the output to be transfers.
Basically, I want a more cleaner way to do this:
if (config.apps) {
answer = 'apps';
} else if (config.transfers) {
answer = 'transfers';
} else if (config.approvals) {
answer = 'approvals';
}
Thanks!
You can use _.findKey():
var config = { apps: false, transfers: false, approvals: true };
var answer = _.findKey(config);
console.log(answer);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>
Or without lodash, you can use Array.prototype.reduce() with Object.keys():
var config = { apps: false, transfers: false, approvals: true };
var answer = Object.keys(config).reduce(function(answer, key) {
return value = config[key] ? key : answer;
}, '');
console.log(answer);
No lodash required:
var config = {
apps: false,
transfers: false,
approvals: true
};
Object.keys(config).find((key) => {
return config[key];
});
A bit newer method then Object.keys is entries with that you can retrieve both the key and the value
let config = {apps: false, transfers: false, approvals: true}
let [key, value] = Object.entries(config).find(([key, val]) => val)
console.log(key, value)
Related
I'm trying to change the values of each property in an array using a forEach function but not having any luck.
Here's my array:
this.panels = [
{ isRandomPanel : false },
{ isMyPanel : false },
{ isFavorite : false },
{ isEatable : false }
]
I'm trying to update the value of each property to true so finally I can get this:
isRandomPanel = true
isMyPanel = true
isFavorite = true
isEatable = true
I'm trying to use the forEach function but I'm stuck:
this.panels.forEach(panel => panel.isRandomPanel = true);
Does anyone know how to make this happen using pure Javascript, TypeScript or ES6?
If those are the only keys on the objects, you can iterate over Object.keys(panel) and set each panel[key] = true, like so:
var panels = [
{ isRandomPanel : false },
{ isMyPanel : false },
{ isFavorite : false },
{ isEatable : false }
];
// set all panel flags to true
panels.forEach(function (panel) {
Object.keys(panel).forEach(function (key) {
panel[key] = true;
});
});
console.log(panels);
Or, with shortened ES6 Syntax:
panels.forEach(panel => Object.keys(panel).forEach(key => panel[key] = true));
You need to itreate over the array, get each key from the object and set the value of that key to true. You can use Object.keys or for in loop to get the keys:
this.panels.forEach(panel => {
for(const key of Object.keys(panel))
panel[key] = true
})
OR
this.panels.forEach(panel => {
for(const key in panel)
panel[key] = true
})
As you are using ES 6, So following will work
panels.forEach(panel => Object.keys(panel).forEach(key => panel[key] = true));
I have a use case where I have an object of varying values, and I need to get all of these keys that have a specific value. For instance, here is a sample object:
myObject = {
Person1: true,
Person2: false,
Person3: true,
Person4: false
};
The key names will vary, but the valid values are true or false. I want to get an array of the names that have a value of true:
myArray2 = [
'Person1',
'Person3
];
I've been trying to use various lodash functions in combination such as _.key() and _.filter, but with no luck. How can I accomplish this? I'm open to pure JS or Lodash options.
UPDATE: I accepted mhodges' answer below as the accepted answer, although others gave me the same answer. Based on that, I came up with a Lodash version:
var myArray = _(myObject).keys().filter(function(e) {
return myObject[e] === true;
}).value();
If I understand your question correctly, you should be able to use basic .filter() for this.
myObject = {
Person1: true,
Person2: false,
Person3: true,
Person4: false
};
var validKeys = Object.keys(myObject).filter(function (key) {
return myObject[key] === true;
});
Since Lodash was tagged: With pickBy the values can be filtered (and the keys obtained with _.keys ):
var myArray2 = _.keys(_.pickBy(myObject));
var myObject = { Person1: true, Person2: false, Person3: true, Person4: false };
var myArray2 = _.keys(_.pickBy(myObject));
console.log(myArray2 );
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
Use Object.keys():
var object = {
1: 'a',
2: 'b',
3: 'c'
};
console.log(Object.keys(object));
Alternative solution:
var keys = [];
for (var key in object) {
if (object.hasOwnProperty(key)) {
keys.push(key);
}
}
console.log(keys);
Don't forget to check a key with the help of hasOwnProperty(), otherwise this approach may result in unwanted keys showing up in the result.
You can do this with Object.keys() and filter().
var myObject = {
Person1: true,
Person2: false,
Person3: true,
Person4: false
};
var result = Object.keys(myObject).filter(function(e) {
return myObject[e] === true;
})
console.log(result)
ES6 version with arrow function
var result = Object.keys(myObject).filter(e => myObject[e] === true)
i'm developing in Javascript and i created folders array that contain objects:
folders = [folder1, folder2, folder3...]
Every object have some properties, one of this is docs that is an array of objects:
docs = [doc1, doc2, doc3...]
...and every object is like this:
doc1.title = 'foo'
doc1.desc = 'bar'
doc1.attr = {new: _.random(0, 1) > 0.5, read: _.random(0, 1) > 0.5}
...
I would like to create a function that extract only docs that have attr = {new: true, read: false}.
I tried some underscore method such as _.each, _.sample, _.find and _.findWhere, but i can't figure out how to get from the main array a sample that contains docs with that attr properties.
Any idea?
Using underscore first flatten the folders and then use where to get what you want:
var result = _.where( _.flatten(folders), {new: true, read: false});
Edited to work with the new structure:
var result = _.chain(folders)
.pluck('docs')
.flatten()
.where({isNew: true, read: false})
.value();
var folders = [
{
docs: [
{
title: 'one',
isNew: true,
read: false
}, {
title: 'two',
isNew: true,
read: true
}
]
},
{
docs:
[
{
title: 'three',
isNew: false,
read: false
}, {
title: 'four',
isNew: true,
read: false
}
]
}
];
var result = _.chain(folders)
.pluck('docs')
.flatten()
.where({isNew: true, read: false})
.value();
document.getElementById('result').textContent = JSON.stringify(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.2/underscore.js"></script>
<p>
<pre id="result"></pre>
</p>
Have you tried something like this?
var result = [];
folders.forEach(function(docs) {
result.concat( docs.filter(function(doc) {
return doc.attr.new && !doc.attr.read;
});
});
underscore methods like .find work on arrays which are one level deep:
var temp = [];
_.each(folders , function(docsArray){
var result = _.where(docsArray , {new: true, read: false});
if(result){
temp.concat(result);
}
});
You can achieve what you want without using underscore or lodash,just
Take advantage of the built-in Array.map and Array.filter methods, here is an example :
var myResult = folders.map(function(folder){
return myCustomDocs = folder.filter(function(doc){
return (doc.attr.new && !doc.attr.read);
});
});
console.log(myResult);
What about a regular filter?
Working Demo
(Simply open your browser console and run the fiddle.)
doc1.filter(o => o.attr.new && !o.attr.read)
And you can also simply map() your folders array.
const _folders = folders
.map(doc => doc.filter(o => o.attr.new && !o.attr.read))
You would get on new folders array containing arrays with only new && !read documents. Which you could flatten if needed:
const flatFolders = [].concat.apply([], _folders)
I found a working solution.
Here is my code:
var result = [];
folders.forEach(function(item) {
result = result.concat(_.filter(item.docs, function(doc) {
return doc.isNew === true && doc.read === false;
}));
});
If you have Node.js 5+ or use Babel, you can just do:
folders.reduce((res, arr) => res.concat(arr), []) // flatten folders
.filter(doc => doc.attr.new && !doc.attr.read); // remove all that don't return true
How would I use lodash to get the following output ?
input = {
'property1' : true,
'property2' : false,
'property3' : false
}
// only pick those properties that have a false value
output = ['property2', 'property3'];
I currently have the following in place:
var output = [];
_.forEach(input, (value, key) => {
if (value === false) {
output.push(key);
}
});
Plain JS you can do:
var output = Object.keys(input).filter(function(k) { return input[k] === false })
You can do something like that using lodash:
const output = _.keys(_.pickBy(input, function(value, key) {return !value }));
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)