CapSap
CapSap

Reputation: 53

Using filter method in JS and some keys are missing/undefined

I am trying to filter a JSON object by a key length i.e. if key length is longer than 70 characters then add to new array, to be rendered later on in react. The below was my first attempt.

// First attempt:
const longJokes = jokesData.filter(x => x.question.length > 60 ) 

The problem that I'm having is that some objects don't have the key and x.question is undefined for some objects. The fix I came up with was to filter the JSON object first and then do the length filter, but now I am missing out on punchline only jokes.

// Second attempt:
const longJokes = jokesData.filter(x => x.question).filter(x => x.question.length > 60 ) 

My question is: Is there a better way to do this/handle missing keys? In the real world do objects within a JSON object have different/missing keys often? I feel like there is a much better way to handle this, but I don't know what im doing.
Maybe I should separately filter and add the missing punchLine only jokes to const longJokes

here is the full code and seperate JSON object below:

import React from "react"

import Joke from "./Joke"
import jokesData from "./jokesData"

function App() {
    const jokeComponents = jokesData.map(
        joke => <Joke key={joke.id} question={joke.question} punchLine={joke.punchLine} />
        )
      
    const longJokes = jokesData.filter(x => x.question).filter(
        x => x.question.length > 60 ).map(joke => <Joke key={joke.id} question={joke.question} punchLine={joke.punchLine} />
        )
    
    console.log(jokesData[0].punchLine)
    console.log(longJokes)
    
    return (
        <div>
            {jokeComponents}
            {longJokes}            
        </div>
    )
}

export default App

// 
const jokesData = [
   {
       id: 1,
       punchLine: "It’s hard to explain puns to kleptomaniacs because they always take things literally."
   },
   {
       id: 2,
       question: "What's the best thing about Switzerland?",
       punchLine: "I don't know, but the flag is a big plus!"
   },
   {
       id: 3,
       question: "Did you hear about the mathematician who's afraid of negative numbers?",
       punchLine: "He'll stop at nothing to avoid them!"
   },
   {
       id: 4,
       question: "Hear about the new restaurant called Karma?",
       punchLine: "There’s no menu: You get what you deserve."
   },
   {
       id: 5,
       question: "Did you hear about the actor who fell through the floorboards?",
       punchLine: "He was just going through a stage."
   },
   {
       id: 6,
       question: "Did you hear about the claustrophobic astronaut?",
       punchLine: "He just needed a little space."
   }
]

export default jokesData 

Thanks

Upvotes: 0

Views: 745

Answers (4)

CapSap
CapSap

Reputation: 53

With the answers and help from @John and @Shuvo this was the solution I came up with. Thank you

const longJokes = jokesData
  .filter(x => x.question !== undefined && x.question.length > 60 ||
      x.punchLine.length > 60
  )
  .map((joke) => (
    <Joke key={joke.id} question={joke.question} punchLine={joke.punchLine} />
  ));

Upvotes: 0

John
John

Reputation: 1092

This can be achieved with a single filter too. You can only check for length when question is defined.

const longJokes = jokesData.filter(x => {
    if (x.question){
        return x.question.length > 60
    }
});

Upvotes: 0

abhay
abhay

Reputation: 642

You can use Optional Chaining Operator ?. in this situation where you don't know about keys.

const jokesData = [
   {
       id: 1,
       punchLine: "It’s hard to explain puns to kleptomaniacs because they always take things literally."
   },
   {
       id: 2,
       question: "What's the best thing about Switzerland?",
       punchLine: "I don't know, but the flag is a big plus!"
   },
   {
       id: 3,
       question: "Did you hear about the mathematician who's afraid of negative numbers?",
       punchLine: "He'll stop at nothing to avoid them!"
   },
   {
       id: 4,
       question: "Hear about the new restaurant called Karma?",
       punchLine: "There’s no menu: You get what you deserve."
   },
   {
       id: 5,
       question: "Did you hear about the actor who fell through the floorboards?",
       punchLine: "He was just going through a stage."
   },
   {
       id: 6,
       question: "Did you hear about the claustrophobic astronaut?",
       punchLine: "He just needed a little space."
   }
]

const longJokes = jokesData.filter(x => x.question?.length > 60 ) 
console.log(longJokes.length)

Upvotes: 1

Shuvo
Shuvo

Reputation: 1293

First, to solve your filter issue:

const longJokes = jokesData.filter(x => x.question !== undefined && x.question.length > 60 ) 

Next, you can map through all the jokes within one iteration:

const jokes = jokesData.map(joke => {
  if (joke.question !== undefined) {
    <Joke key={joke.id} question={joke.question} punchLine={joke.punchLine} />
  } else {
    <Joke key={joke.id} punchLine={joke.punchLine} />
  }
});

Upvotes: 0

Related Questions