0
let obj = {
  tom: {
    id: 0
  },
  david: {
    id: 1
  },
  john: {
    id: 2
  }
}

let ids = [1, 2]

I want to filter the obj based on ids.

The result I want is

{ david: { id: 1 }, john: { id: 2 } }

Because ids above is [1, 2].

I want to do this with Ramda.js.

Plase help me.


Ok, I'm sorry.

I did something like this.

let obj2 = {}
ids.forEach((x) => {
      obj2 += R.filter(y => y.id === x, obj)
      })
obj = obj2

But, it is not correct.

And I don't want to use forEach.

I want to do with Ramda.js .

3
  • 2
    The posted question does not appear to include any attempt at all to solve the problem. StackOverflow expects you to try to solve your own problem first, as your attempts help us to better understand what you want. Please edit the question to show what you've tried, so as to illustrate a specific roadblock you're running into in a Minimal, Complete, and Verifiable example. For more information, please see How to Ask and take the tour. Commented Mar 8, 2019 at 3:57
  • I am sorry. I edited the question little bit. Commented Mar 8, 2019 at 4:06
  • I have updated my answer with an example of how to approach what you want using Ramda sintax. Commented Mar 8, 2019 at 4:33

5 Answers 5

2

You can do this only using Javascript, first you can create a set with the ids you want to keep (check if set has an element is O(1)). Then, you can loop on the original object and add the key with his value on a new object if the set has the related id:

let obj = {
  tom: {id: 0},
  david: {id: 1},
  john: {id: 2}
}
let ids = [1, 2];

const filterByIds = (obj, ids) =>
{
    let idsSet = new Set(ids);
    let filteredObj = {};

    for (k in obj)
    {
        if (idsSet.has(obj[k].id))
            filteredObj[k] = obj[k];
    }
    
    return filteredObj;
}

console.log(filterByIds(obj, ids));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}


Update to use Ramda:

With Ramda you can do like this:

let obj = {
  tom: {id: 0},
  david: {id: 1},
  john: {id: 2}
}
let ids = [1, 2];
let idsSet = new Set(ids);

const hasValidId = o => idsSet.has(o.id);
let res = R.filter(hasValidId, obj);
console.log(res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

Easy if you read the documentation here

Sign up to request clarification or add additional context in comments.

2 Comments

So great. Thank you so much.
Note that depending on the size of ids, the Set isn't particularly necessary, as you could replace idSet.has(o.id) with ids.includes(o.id). Yes this is O(n) rather than about O(1), but for many cases, it's indistinguishable.
1

You can do it in pure JavaScript by using Object.entries and destructuring with includes like so:

let obj = {
  tom: {
    id: 0
  },
  david: {
    id: 1
  },
  john: {
    id: 2
  }
};

let ids = [1, 2];

let result = {};

Object.entries(obj).forEach(([name, { id }]) => {
  if (ids.includes(id)) {
    result[name] = { id: id };
  }
});

console.log(result);

3 Comments

Thank you so much! But I want to do with Ramda.js(T_T)
Since Ramda.JS is a JavaScript framework, everything that can be done in Ramba can be done in pure JavaScript.
While this is technically true, with a similar argument, every single SPAs in the world could be rewritten in plain JavaScript, which is very unlikely to happen. People often use frameworks to facilitate and bring structure into their software delivery cycle. Ultimately it comes down to using the right tool for the job, which isn't always an easy decision to make.
1

Generally speaking, you should strive to work with data structures that help you rather than work against you.

With a simplified data structure such as this one below:

const obj = [
  {id: 0, name: 'tom'},
  {id: 1, name: 'david'},
  {id: 2, name: 'john'}
]

You could use innerJoin:

innerJoin((cur, id) => cur.id === id, obj, [1, 2])

How to convert your original data structure into a simplified one?

It can be a two-step process with Ramda:

  1. Split your object into an array of key/value pairs with toPairs:

    {tom:{id:0}} ~> [['tom', {id: 0}]]
    
  2. Map each pair into an object:

    [['tom', {id: 0}]] ~> [{name: 'tom', id: 0}]
    

const obj = {
  tom: {
    id: 0
  },
  david: {
    id: 1
  },
  john: {
    id: 2
  }
}

const convert = R.compose(R.map(([name, id]) => ({name, ...id})), R.toPairs);

console.log(convert(obj))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>

Comments

0

Try This:

let obj = { tom: { id: 0 }, david: { id: 1}, john: {id: 2} }
let ids = [1, 2] ;
let result = {} ;

for ( var o in obj ) {
  if (ids.includes(obj[o].id))
    result[o] = obj[o];
}

console.log(result) ;

Comments

0

Unless this is an exercise in learning Ramda, beware of the idea of wanting to do this in Ramda. I'm one of the primary authors of Ramda, and a big fan, but I need to stress that it's simply a toolkit than can help in some situations. When it helps, great, but it shouldn't be a goal.

Now, I do think it can help here. This is what I would do with Ramda:

const matchIds = (obj, ids) => filter(propSatisfies(includes(__, ids), 'id'), obj)

let obj = {tom: {id: 0}, david: {id: 1}, john: {id: 2}}
let ids = [1, 2]

console.log(matchIds(obj, ids))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>
const {__, filter, propSatisfies, includes} = R
</script>

An alternative, especially if the list of ids is less likely to change than the object, is this:

const matchIds = (ids) => filter(propSatisfies(includes(__, ids), 'id'))

let obj = {tom: {id: 0}, david: {id: 1}, john: {id: 2}}
let ids = [1, 2]

console.log(matchIds(ids)(obj))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>
const {__, filter, propSatisfies, includes} = R
</script>

There are some reasons not to like the placeholder ('__'). If you feel that way, you can replace includes(__, ids) with flip(includes)(ids).

Update

I don't take my own advice here. While I still would use Ramda for the filter, there is no need for propSatisfies here. A simple lambda would be perfectly fine:

const matchIds = (ids) => filter(({id}) => ids.includes(id))

This is much cleaner and more readable, at least once you're used to the Ramda norm of partial application. (filter takes two arguments: the predicate function and the object to filter with it. Since we only supply the first, this gives us back a function expecting the second. When we call that resulting function with the object, the filtering happens.)

The reason I would still use Ramda's filter is that there is no direct built-in version of it as applied to objects. Ramda supplies a simple alternative to writing a one-off object filtering.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.