17

I have an array of the object like below :

[{name:'name', key:'21',good: 'true'},
{name: 'another name', key:'22',good:'false'},
...]

now I want to make a change in one of the objects in this array. My first try was this:

const s = R.compose(
  R.assoc('good', checked),
  R.propEq('key', name),
  R.map(),
);

but this code results in that object which I want and only its 'good' property. I want to get the whole array with that change.

Max Desiatov
  • 5,087
  • 3
  • 48
  • 56
amir
  • 2,443
  • 3
  • 22
  • 49

3 Answers3

28

I would do it something like this:

const alter = curry((checked, key, items) => map(
  when(propEq('key', key), assoc('good', checked)),
  items
))

alter('true', '22', items)

This has the advantage of including no free variables (such as checked and name in the original.) The currying can be dropped if you're never going to need partial versions of this.

You can see this in action on the Ramda REPL.

Update, 2023-05-05: the order of arguments to propEq has recently changed. We would need to swap the parameters in the above, as seen in the REPL.

Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
  • Hi Scott! I hope you are doing well! Thanks for your beautiful library, but here might be a problem with it. Change the version to ?v=0.29.0 in the REPL link in your comment and see the difference. – scythargon May 05 '23 at 19:03
  • @scythargon: The order of arguments to `propEq` [changed in v0.29.0](https://github.com/ramda/ramda/issues/3369), one of our few intentional breaking changes over the years. This would need to be reworked. – Scott Sauyet May 05 '23 at 19:59
  • [Updated version](https://ramdajs.com/repl/#?const%20items%20%3D%20%5B%0A%20%7Bname%3A%27name%27%2C%20key%3A%2721%27%2Cgood%3A%20%27true%27%7D%2C%0A%20%7Bname%3A%20%27another%20name%27%2C%20key%3A%2722%27%2C%20good%3A%27false%27%7D%2C%0A%5D%0A%0Aconst%20alter%20%3D%20curry%28%28checked%2C%20key%2C%20items%29%20%3D%3E%20map%28%0A%20%20when%28propEq%28key%2C%20%27key%27%29%2C%20assoc%28%27good%27%2C%20checked%29%29%2C%0A%20%20items%0A%29%29%0A%0Aalter%28%27true%27%2C%20%2722%27%2C%20items%29%0A) on the REPL. – Scott Sauyet May 05 '23 at 20:06
4

I had to make some assumptions about the value fo checked and name.

let checked = 'true'
let name = '22'

let input = [{name:'name', key:'21',good: 'true'},
{name: 'another name', key:'22',good:'false'}]

const update = R.map(R.ifElse(R.propEq('key', name), R.assoc('good', checked), (item) => item))

console.log(update(input))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.24.1/ramda.min.js"></script>
Chris Phillips
  • 673
  • 5
  • 10
  • 3
    Three points: (1) `(item) => item` could also be written `R.identity`. (2) `ifElse(pred, fn, identity)` has a shorthand in `when(pred, fn)`. (3) Using free variables such as `checked` and `name` means this isn't referentially transparent, which is a Bad Thing (TM) in functional programming. It would be clearer if these were also parameters to the function. -- See my answer for a version which fixes these. – Scott Sauyet Oct 08 '17 at 14:23
  • 1
    Thanks for the clarifications. I'm new to ramda and there are so many functions, I knew there should be something that did (item) => item, but failed to find it :) – Chris Phillips Oct 09 '17 at 06:32
0

I would use Ramda's find, findIndex and update combined. Let's say your array's name is array and you would like to change the key from the second object of your array. And you would like to to change from '22' to '40'.

const objToChange = R.find(R.propEq('key', 22 ))(array); // To find the object you like to change.
objToChange.key = 40; // Change your desired field.
R.update(R.findIndex(R.propEq('key', 22))(array), objToChange, 
patients); // And update the array with the new changed object.

Or just using findIndex ...

const index = R.findIndex(R.propEq('key', 22))(patients);
array[index].key = 40;
ikranas
  • 1
  • 1