1

My data structure (condensed)

const data = {
  "cars": [
    {
      "name": "toyota",
      "sedan": {
        "2d": [
          {
            "name": "corolla",
            "year": 2020
          },
          {
            "name": "supra",
            "year": 1986
          }
        ]
      }
    }
  ]
};

To find the object by name, I would do:

const twoDcars = data.cars.reduce(car => car.sedan);
const match = twoDcars.sedan['2d'].filter(car => car.name === "corolla");
console.log(match); //[ { name: 'corolla', year: 2020 } ]

With conditional check:

const twoDcars = data.cars && data.cars.reduce(car => car.sedan);
const match = twoDcars && twoDcars.sedan && twoDcars.sedan['2d'] && twoDcars.sedan['2d'].filter(car => car && car.name === "corolla");
console.log(match);  //[ { name: 'corolla', year: 2020 } ]

With try/catch:

let match;
try {
  match = data.cars.reduce(car => car.sedan).sedan['2d'].filter(car => car.name === "corolla");
} catch {}
console.log(match); //[ { name: 'corolla', year: 2020 } ]

My question is, what is the preferred/industry-standard of doing this.

  • A && A.B && A.B.C && A.B.C.D
  • try {A.B.C.D} catch{}
  • Some other approach?

My requirement is pretty simple.

  • Find the match if possible
  • App shouldn't break on any conditions.

What am I trying to do is avoid hundreds of && or `try{}catch{}`` everywhere in my code. I can create utility methods whenever possible but with the complex/nested data that I'm dealing with, it is often impossible.

10
  • Trying with an empty catch is almost certainly not what you want. Commented Oct 26, 2019 at 20:57
  • @ChiefTwoPencils What is the downside? Upside is any exception will not break my app-flow. Commented Oct 26, 2019 at 21:01
  • Downside is you won't even know it happened or why. See this. Commented Oct 26, 2019 at 21:03
  • 1
    reduce(car => car.sedan) doesn't make sense. Did you mean find or still something else? Commented Oct 26, 2019 at 21:09
  • 1
    @ChiefTwoPencils That is the problem. I am currently debating between transforming the data before it can be used vs using the raw data. Commented Oct 26, 2019 at 22:18

2 Answers 2

1

If possible, I would probably do some massaging of the raw data to get it in a form where you can filter down at the top level and ensure you're not dealing with all the possible nulls everywhere in you code. I'd also get rid of the check on cars by ensuring there's always an empty list of cars. That way, filter and the rest will just work.

I would probably shoot to flatten the car objects into individual cars with all the props; like so:

const data = {
  "cars": [
    {
      "year": 2020,
      "make": "toyota",
      "model": "corolla",
      "type": "sedan",
      "doors" : 2
    },
    {
      "year": 1986,
      "make": "toyota",
      "model": "supra",
      "type": "sedan",
      "doors" : 2
    }
  ]
};

I wouldn't use multiple chained filters for this I'm just showing how much easier it would be to filter more directly and get all sedans, two-door sedans, etc. simplifying your code and life :)

let results = data
  .cars
  .filter(car => car.type === 'sedan')     // all sedans
  .filter(car => car.doors === 2)          // two-door sedans
  .filter(car => car.model === 'corolla'); // two-door corollas

Of course, once you massage it, you can reorder the filters to be more direct; like so (assuming you know a corolla is a sedan and you want only two-door models):

let results = data
  .cars
  .filter(car => car.model === 'corolla' && car.doors === 2);
Sign up to request clarification or add additional context in comments.

Comments

0

Whether to use try/catch or to add in the guarding conditions, is a matter of opinion, although I have seen more often the guarded expressions.

But there is no doubt that we're all going to be fans of the conditional chaining feature (also: mdn), currently in stage 3.

Then your code would look like:

const match = data.cars?.find(car => car.sedan)
              ?.sedan?.['2d']?.filter(car => car?.name === "corolla");

If searches in a nested object are frequent, then you could consider to flatten the structure into an array of non-nested objects.

To avoid a scan of the whole array, you could sort that array by one of its object-properties, allowing for a binary search. You can even add some Map objects as separate ways to access the same data, but by key. This obviously brings you back to more nesting, but it would be an additional structure (not replacing the array) for drilling down into your data faster than by filtering the whole lot. Such a Map would hold per key an array of matching objects (no copies, but the same object references as in the main array).

1 Comment

I'll certainly be a fan of the feature but not of this usage. While it works and is more compact, needing to use it like in the example seems to be a symptom of poor decisions elsewhere IMHO.

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.