7

Im trying to filter out objects with a delete: false to then only map and render this objects to screen but I'm not sure how to get it to work.

Sample object

{
  "8xf0y6ziyjabvozdd253nd": {
    "id": "8xf0y6ziyjabvozdd253nd",
    "timestamp": 1467166872634,
    "title": "Udacity is the best place to learn React",
    "body": "Everyone says so after all.",
    "author": "thingtwo",
    "category": "react",
    "voteScore": 6,
    "deleted": false
  }
}

Method for finding key and map.

const {posts} = this.props
        return _.find(posts, { 'deleted': false })_.map(posts, post => {
            return (
                <div key={post.id}>
Petter Östergren
  • 973
  • 4
  • 14
  • 27

5 Answers5

8

Basically, you can apply lodash#reduce to Object directly instead of getting all the keys first, and then iterating again. And with reduce you can do the map and filtering together.

_.reduce(obj, (i, v, k)=> !v.deleted && !(i[k] = v) || i, {});

Let's create a working example for you, Here is a code snippet:

var obj = {
  "9ny0z4ziyjabvozdc713dr": {
    "id": "9ny0z4ziyjabvozdc713dr",
    "timestamp": 1467166879723,
    "title": "StackOverfow is the best place to learn Angular",
    "body": "bla bla bla bla.",
    "author": "myself",
    "category": "angular",
    "voteScore": 9,
    "deleted": true
  },
    "8xf0y6ziyjabvozdd253nd": {
    "id": "8xf0y6ziyjabvozdd253nd",
    "timestamp": 1467166872634,
    "title": "Udacity is the best place to learn React",
    "body": "Everyone says so after all.",
    "author": "thingtwo",
    "category": "react",
    "voteScore": 6,
    "deleted": false
  }
}

var finalObj =_.reduce(obj, (i, v, k)=> !v.deleted && !(i[k] = v) || i, {});

console.log(finalObj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

EDIT

For the specific case (of OP), just some key/value pair needs to be removed and construct a new object, then better to use lodash#omitBy to simply remove some entries from an object against some condition. Here is a simple example of this particular use.

_.omitBy(obj, o=>o.deleted);

Here is the code snippet for this example:

var obj = {
      "9ny0z4ziyjabvozdc713dr": {
        "id": "9ny0z4ziyjabvozdc713dr",
        "timestamp": 1467166879723,
        "title": "StackOverfow is the best place to learn Angular",
        "body": "bla bla bla bla.",
        "author": "myself",
        "category": "angular",
        "voteScore": 9,
        "deleted": true
      },
        "8xf0y6ziyjabvozdd253nd": {
        "id": "8xf0y6ziyjabvozdd253nd",
        "timestamp": 1467166872634,
        "title": "Udacity is the best place to learn React",
        "body": "Everyone says so after all.",
        "author": "thingtwo",
        "category": "react",
        "voteScore": 6,
        "deleted": false
      }
    }

    var finalObj =_.omitBy(obj, o=>o.deleted);

    console.log(finalObj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

However, If any transformation needed in between (Array or Object), or the output type needs to be customized then I will still prefer to suggest to use reduce.

Koushik Chatterjee
  • 4,106
  • 3
  • 18
  • 32
2

If you want to filter, the easiest thing to use is an actual filter. I'm not very familiar with React, but the Lodash chain below will work, if React supports more complex chains.

I noticed you have a nested object, if that is intentional, then the code below will do the trick:

// I added some fake posts to make the data more illustrative 

let posts = [{
    "8xf0y6ziyjabvozdd253nd": {
        "id": "8xf0y6ziyjabvozdd253nd",
        "timestamp": 1467166872634,
        "title": "Udacity is the best place to learn React",
        "body": "Everyone says so after all.",
        "author": "thingtwo",
        "category": "react",
        "voteScore": 6,
        "deleted": false
    }
}, {
    "8888ziyjabvozdd253nd": {
        "id": "8888ziyjabvozdd253nd",
        "timestamp": 1467166872634,
        "title": "Udacity is the best place to learn React",
        "body": "Everyone says so after all.",
        "author": "thingtwo",
        "category": "react",
        "voteScore": 6,
        "deleted": true
    }
}, {
    "77776ziyjabvozdd253nd": {
        "id": "77776ziyjabvozdd253nd",
        "timestamp": 1467166872634,
        "title": "Udacity is the best place to learn React",
        "body": "Everyone says so after all.",
        "author": "thingtwo",
        "category": "react",
        "voteScore": 6,
        "deleted": false
    }
}, {
    "6666ziyjabvozdd253nd": {
        "id": "6666ziyjabvozdd253nd",
        "timestamp": 1467166872634,
        "title": "Udacity is the best place to learn React",
        "body": "Everyone says so after all.",
        "author": "thingtwo",
        "category": "react",
        "voteScore": 6,
        "deleted": true
    }
}, {
    "55556ziyjabvozdd253nd": {
        "id": "55556ziyjabvozdd253nd",
        "timestamp": 1467166872634,
        "title": "Udacity is the best place to learn React",
        "body": "Everyone says so after all.",
        "author": "thingtwo",
        "category": "react",
        "voteScore": 6,
        "deleted": false
    }
}];

// you'd just return _(posts) here directly, but I'm assigning a variable so we can show the console log for this snippet
const filteredPosts = _(posts)
    .filter(post => {
        const objectKey = Object.keys(post)[0];
        const innerData = post[objectKey];
        return innerData.deleted === false
    })
    .map(post => {
        const objectKey = Object.keys(post)[0];
        // your return would be in the format of <div key={objectKey}>
      return  `<div key={${objectKey}}>`
    })
    .valueOf();




console.log(filteredPosts);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

If the nesting of the object isn't intentional, then getting the info will be more straightforward and cleaner. If your actual objects look like the sample ones I have below, you could access the data like this:

let posts = [{
        "id": "8xf0y6ziyjabvozdd253nd",
        "timestamp": 1467166872634,
        "title": "Udacity is the best place to learn React",
        "body": "Everyone says so after all.",
        "author": "thingtwo",
        "category": "react",
        "voteScore": 6,
        "deleted": false
}, {
        "id": "8888ziyjabvozdd253nd",
        "timestamp": 1467166872634,
        "title": "Udacity is the best place to learn React",
        "body": "Everyone says so after all.",
        "author": "thingtwo",
        "category": "react",
        "voteScore": 6,
        "deleted": true
}, {
        "id": "77776ziyjabvozdd253nd",
        "timestamp": 1467166872634,
        "title": "Udacity is the best place to learn React",
        "body": "Everyone says so after all.",
        "author": "thingtwo",
        "category": "react",
        "voteScore": 6,
        "deleted": false
}];

// you'd just return _(posts) here directly, but I'm assigning a variable so we can show the console log for this snippet
const filteredPosts = _(posts)
    .filter(post => {
        return post.deleted === false
    })
    .map(post => {
        // your return would be in the format of <div key={post.id}>
      return  `<div key={${post.id}}>`
    })
    .valueOf();




console.log(filteredPosts);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
1

The result of _.find is an array, so if you want to map the elements in that array you should _.map(result)

const {posts} = this.props;
return _.map(_.find(posts, { 'deleted': false }), post => {
            return (
                <div key={post.id}>
Dekel
  • 60,707
  • 10
  • 101
  • 129
1

If you want to skip lodash, the native API of javascript array will offer you a solution like the following:

const { posts } = this.props;

return posts
    .find(post => !post.deleted)
    .map(post => {
        return (
            <div key={post.id}>...
SALEH
  • 1,552
  • 1
  • 13
  • 22
  • I didn't see your answer while replying to this question. Anyway, edited my answer a bit @Dekel – SALEH Sep 14 '17 at 21:43
  • 1
    This answer is wrong. `posts.find` should get a function... not the element and an object. Double check before you post. – Dekel Sep 14 '17 at 21:46
  • @Dekel, isn't that the syntax for an inline function? It doesn't need brackets for the parameter (since there is just one), and it doesn't need curly braces for the function code (since it's on one line). – Brendon Muir Nov 17 '21 at 01:04
  • @BrendonMuir My comment was before the edit of the answer :-) – Dekel Nov 17 '21 at 08:38
  • Right you are there :D – Brendon Muir Nov 17 '21 at 09:59
  • 2
    This is wrong. `find` returns a single instance or `undefined` if there is no match. `map` is available on an array. `map` will not work chained like this. – Matt Byrne May 04 '22 at 06:12
0

you can do that in the following way

let obj = {
  "8xf0y6ziyjabvozdd253nd": {
    "id": "8xf0y6ziyjabvozdd253nd",
    "timestamp": 1467166872634,
    "title": "Udacity is the best place to learn React",
    "body": "Everyone says so after all.",
    "author": "thingtwo",
    "category": "react",
    "voteScore": 6,
    "deleted": false
  }
}

let result = Object.keys(obj).reduce((a, b) =>{
    if(obj[b].deleted != false){
        a[b] = obj[b];
    }
    return a;
}, {});

console.log(result);
marvel308
  • 10,288
  • 1
  • 21
  • 32