How to extract second level keys out of two level map using lodash - lodash

I have a data structure like this
{
'a' : { 'aa' : { b: 1, c: 2}},
'b' : { 'bb' : { c: 3, d: 4}},
'c' : { 'cc' : { c: 3, d: 4}}
}
I'd like to map it using lodash into a flat structure like this:
{
'aa' : { b: 1, c: 2}},
'bb' : { c: 3, d: 4}},
'cc' : { c: 3, d: 4}},
}
I can do it using a side effect based approach with the code like this:
const flattened = {};
_(state.values)
.map(e => _.forEach(e, (e, k) => flattened[k] = e))
.value();
It does the job, but I am looking for a nicer pure functional way to do this.

Get the values of the original object, and merge them into a new object:
const obj = {
'a' : { 'aa' : { b: 1, c: 2}},
'b' : { 'bb' : { c: 3, d: 4}},
'c' : { 'cc' : { c: 3, d: 4}}
}
const result = _.merge({}, ..._.values(obj))
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

Related

How to merge objects with Lodash, but replace arrays values?

I'm trying to replace arrays of an old object with values from a new object which has arrays... I guess it will make sense when you see an example and desire result:
https://jsfiddle.net/redlive/9coq7dmu/
const oldValues = {
a: 1,
b: [2, 21, 22, 23],
c: {
d: 3,
e: 4,
f: [5, 6, 7]
}
};
const updatedValues = {
b: [],
c: {
f: [8]
}
}
const result = _.merge( oldValues, updatedValues );
console.log(result);
/* Desire result:
{
a: 1,
b: [],
c: {
d: 3,
e: 4,
f: [8]
}
}
*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>
Use _.mergeWith(), and if the 2nd value is an array, return it. If not return undefined, and let merge handle it:
const oldValues = {"a":1,"b":[2,21,22,23],"c":{"d":3,"e":4,"f":[5,6,7]}};
const updatedValues = {"b":[],"c":{"f":[8]}};
const result = _.mergeWith(oldValues, updatedValues, (a, b) =>
_.isArray(b) ? b : undefined
);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>

Reducing to list of object from object key and value

Given a previous Ramda groupBy to
{
'2018-Q4': 2,
'2019-Q1': 5
}
How can I map this to
[
{'quarter': '2018-Q4', 'value': 2},
{'quarter': '2019-Q1', 'value': 5},
]
Convert to pairs and then zipObj with the field names:
const { pipe, toPairs, map, zipObj } = R
const fn = pipe(
toPairs,
map(zipObj(['quarter', 'value']))
)
const data = {
'2018-Q4': 2,
'2019-Q1': 5
}
const result = fn(data)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>

How group and count elements by lodash

has data
items = {
0: {id:1,name:'foo'},
1: {id:2,name:'bar'},
2: {id:1,name:'foo'}
};
I wont get counted elements like this
result = {
0: {id:1,name:'foo', count:2},
1: {id:2,name:'bar', count:1}
};
lodash has function _.countBy(items, 'name') it's got {'foo': 2, 'bar':1}, i need id too.
If pure JS approach is acceptable, you can try something like this:
Logiic:
Loop over array and copy the object and add a property count and set it to 0.
Now on every iteration update this count variable.
Using above 2 steps, create a hashMap.
Now loop over hashMap again and convert it back to array.
var items = [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}, {
id: 1,
name: 'foo'
}
];
var temp = items.reduce(function(p,c){
var defaultValue = {
name: c.name,
id: c.id,
count: 0
};
p[c.name] = p[c.name] || defaultValue
p[c.name].count++;
return p;
}, {});
var result = [];
for( var k in temp ){
result.push(temp[k]);
}
console.log(result)

"Count where" in a collection

Using lodash, what would be a good way to count the number of objects in a collection conditionally? Say I wanted to count the number of objects where
a < 4
in the following collection
[{a : 1}, {a : 2}, {a : 3}, {a : 4}, {a : 5}, {a : 6}]
Solution
You can use countBy:
const total = _.countBy(
array,
({ a }) => a < 4 ? 'lessThanFour' : 'greaterThanFour'
).lessThanFour
Alternative
Using sumBy:
const total = _.sumBy(
array,
({ a }) => Number(a < 4)
);
And here's the same but with lodash/fp:
const count = _.sumBy(_.flow(_.get('a'), _.lt(4), Number), objects);
Below you can find an easy way to achieve that using the filter method:
var b = _.filter(a, function(o) { if (o.a < 4) return o }).length;
You can use _.countBy:
const count = _.countBy(arr, o => o.a < 4).true

Union of 2 objects with Lodash?

I have 2 objects:
var obj1 = { a:1, b:2, c:3 };
var obj2 = { a:4, c:5, d:6 };
How could I get the union of these 2 objects with lodash? I expect the result to be:
{ a:4, c:5 }
Here is a one-line and readable snippet:
_.pick(obj2, _.intersection(_.keys(obj1), _.keys(obj2)))
// {a: 4, c: 5}
jsfiddle: http://jsfiddle.net/ze8g0p22/