object method like array.find() for deep nested object iteration

Hey!

Currently (with my current knowledge), the only way to iterate through a deeply nested object and stuff like find specific values, return true if they're fund, replace them, etc its only possible with a recursive function. while functional, it can sometimes be a bit too much code for the task.

I was wondering if it's possible to get some methods for objects that act like the ones we have for arrays, such as find, filter, flat to infinity, etc...

const carBrands = [
  {
    Audi: {
      models: ["A1", "A2", "A3", "A4"],
      unitsAvailable: 378,
    }
  },
  {
    BMW: {
      models: ["M1", "M2", "M3", "M4"],
      unitsAvailable: 413,
    },
  },
  {
    Honda: {
      models: ["H1", "H2", "H3", "H4"],
      unitsAvailable: 226,
    },
  }
];

would be awesome to have a similar method to just do something like

carBrands.includesDeep("H1") and have it return true for example!

Thanks for reading!

I think that would be unpractical for real-world problems. What if the data is huge or unstructured ?
That would be like looking for a sequence of binary value inside raw bytes.

1 Like

While this may be more convenient, I'd actually prefer more explicit code to go through a deeply nesting object like this, perhaps with the help of some helper functions to iterate over it. This has a couple of advantages:

  • The code is more robust against future changes - this code should only be looking inside the models array for this entry, but instead it's looking inside of everything. What if some other unrelated property has this property value as well? The code would be broken.
  • It's difficult to refactor code like this. Someone reading legacy code with includesDeep() in it can't tell if the author only wanted to search through brands, or if there was some edge case where they actually expected to find this property value elsewhere. How can code like this be safetly refactored if the original author never documented their intentions of what they actually were trying to search for?

I know today's solution can be rather verbose, and perhaps there's things we can do to make it less verbose. I, for one, am looking forward to the iterator-helper proposal - this would let you make effecient helper functions for consuming complex data like this, which can take away some of the pain.

function* getModels(carBrands) {
  for (const brandContainer of carBrands) {
    for (const brand of Object.values(brandContainer) {
      yield* brand.models
    }
  }
}

// elsewhere...

getModels(carBrands).some(model => model === 'A1')

Of course, this kind of thing can be easily done today if you're ok with making a getModels() function that returns an array instead of an iterator.

2 Likes