17

http://ramdajs.com/0.21.0/docs/#prop

Ramda Repl

var myObject = {a: 1, b: 2, c: 3, d: 4};

var newObject = R.filter(R.props('a'), myObject);
//var newObject = R.filter(R.equals(R.props('a')), myObject);

console.log('newObject', newObject);

Right now the code above is returning the entire object:

newObject {"a":1,"b":2,"c":3,"d":4}

What I would like to do is just return a new object with just the 'a' key. Or a new object with the a and b keys.

Leon Gaban
  • 36,509
  • 115
  • 332
  • 529

4 Answers4

21

Use pick:

let newObj = R.pick(['a'], oldObj);

If your filtering criteria is more complex than just existence, you can use pickBy to select via arbitrary predicate functions.

Jared Smith
  • 19,721
  • 5
  • 45
  • 83
10

The answer from Jared Smith is great. I just wanted to add a note on why your code did not work. You tried

R.filter(R.props('a'), {a: 1, b: 2, c: 3, d: 4});

First of all, you pointed to the documentation for prop, but used props. These are different, but related, functions. prop looks like

// prop :: k -> {k: v} -> v
prop('c', {a: 1, b: 2, c: 3, d: 4}); //=> 3

(there is some added complexity regarding undefined.)

props on the other hand takes multiple values

// props :: [k] -> {k: v} -> [v]
props(['a', 'd'], {a: 1, b: 2, c: 3, d: 4}); //=> [1, 4]

But neither of these is going to be useful input to filter, which for these purposes we can think of as

// filter :: (k -> Bool) -> {k: v} -> {k: v}

The first parameter to filter is a function from a (string) key to a boolean; it works with Javascript's idea that everything is truth-y except for a few specific values. It will be called with each key in turn. So for example, when deciding whether to include {c: 3}, it calls props('a')('c'), which for another slightly odd reason*, actually works, returning [3], which is treated as truth-y, and the filter function will include {c: 3} in its output. So too every key will be included.


* The reason props('a', obj) works when it really should be props(['a'], obj) is that in JS, strings are close enough to lists, having a length property and indexed values. 'a'.length; ==> 1, 'a'[0]; //=> 'a'. Hence props can treat single-character strings as though they were one-element lists of character strings. But it can be a bit bizarre, too: R.props('cabby', {a: 1, b: 2, c: 3, d: 4}); //=> [3, 1, 2, 2, undefined].

Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
5

pickBy()

const getOnlyGoods = R.pickBy((_, key) => key.includes('good'));

const onlyGoods = getOnlyGoods({
  "very good":    90,
  "good":         80,
  "good enough":  60,
  "average":      50,
  "bad":          30,
  "":           10,
});

console.log(onlyGoods);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
Yairopro
  • 9,084
  • 6
  • 44
  • 51
1

Adding to the other answers, there's also omit to filter out specific props.

omit(["a"], { a: 1, b: 2 }) // -> { b: 2 }
bcye
  • 758
  • 5
  • 22