Reputation: 37133
I am trying to update a value in an array in a nested object structure using Ramda.
I want to update the value prop of the object in C
with the name blah
const o = {
A: {
B: {
C: [
{name: 'blah', value: 'blah'},
{name: 'vtha', value: 'blah'},
]
}
}
}
I've been plying with lenses, but it seems quite verbose and I figure I am doing it wrong.
Ideally, I would love something that returns a new object.
const res = fn(o)
{
A: {
B: {
C: [
{name: 'blah', value: 'vtha'}
{name: 'vtha', value: 'blah'},
]
}
}
}
Upvotes: 2
Views: 4185
Reputation: 6633
To update the array in the object we need the path to the array. Then we can update the result with a lens and a helper function adjustIfSatisfies
const { propEq, identity, over, assoc, curry, lensPath, map, ifElse } = R
const o = {
A: {
B: {
C: [
{name: 'blah', value: 'blah'},
{name: 'vtha', value: 'blah'},
]
}
}
}
const adjustIfSatisfies = curry(
(pred, updateFn, samples) => {
return map(ifElse(pred, updateFn, identity), samples)
}
)
const result = over(
lensPath(['A', 'B', 'C']),
adjustIfSatisfies(
propEq('name', 'blah'),
assoc('value', 'vtha')
),
o
)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
Upvotes: 0
Reputation: 45121
If you want to do it in immutable way it would be like
const fn = over(
R.lensPath(['A', 'B', 'C']),
R.map(
o => o.name === 'blah' ? R.assoc('value', 'vtha', o): o
)
)
If you want to avoid manually defining functions by all means you could replace mapped function with
R.ifElse(
R.propEq('name', 'blah'),
R.assoc('value', 'blah'),
R.identity
)
But imho ternary operator looks more readable here.
Upvotes: 4
Reputation: 54
You could try using filter and where, i wrote an example below.
const o = {
A: {
B: {
C: [
{name: 'blah', value: 'blah'},
{name: 'vtha', value: 'blah'},
]
}
}
};
var pred = R.filter(R.where({name: R.contains('blah')}));
pred(o.A.B.C);
Upvotes: 1