1

I need to match values from two JSON sources. Using the javascript find method this way works for me when the nesting of the "cities" array is one level more shallow (just an array of objects), but it's not working with deeper nesting (an array of objects within an array of objects).

Essentially, what I am trying to do is loop through the feeds[0].feed.details.place array and find the matching cities.CountyPlaces.PlaceFIPSCode value for each. I actually need the entire "place" object, so I can utilize any data within for each match.

// console.log(feeds[0].feed.details.place);
// console.log(cities[1].CountyPlaces[2].PlaceName);
feeds[0].feed.details.place.map(async (arrItem, z) => {
  // console.log('arrItem: ', arrItem);
  const cityMatch = await cities.find((cityObject, i) => {
    // console.log(i, 'cityObject: ', cityObject);
    arrItem === cityObject.PlaceName;
  });
  if (cityMatch !== undefined) {
    // --> THIS IS WHERE I NEED TO MANIPULATE MATCHING DATA
    console.log(
      z,
      'cityMatch: ',
      arrItem,
      cityMatch.PlaceName,
      cityMatch.PlaceFIPSCode
    );
  } else {
    // there should be a defined match for every "place" and no else results
    console.log(z, '💥 cityMatch UNDEFINED', arrItem);
  }
});

Here is a simplified example of the data I am using, with identical nesting:

const feeds = [
  {
    feed: {
      record: '0002',
      details: {
        county: ['Alameda'],
        place: ['Alameda', 'Berkeley', 'Oakland'],
      },
    },
  },
];
const cities = [
  {
    CountyName: 'San Francisco',
    CountyFIPSCode: '075',
    CountyPlaces: [
      {
        PlaceName: 'San Francisco',
        PlaceFIPSCode: '67000',
      },
    ],
  },
  {
    CountyName: 'Alameda',
    CountyFIPSCode: '001',
    CountyPlaces: [
      {
        PlaceName: 'Alameda',
        PlaceFIPSCode: '00562',
      },
      {
        PlaceName: 'Albany',
        PlaceFIPSCode: '00674',
      },
      {
        PlaceName: 'Berkeley',
        PlaceFIPSCode: '06000',
      },
      {
        PlaceName: 'Emeryville',
        PlaceFIPSCode: '22594',
      },
      {
        PlaceName: 'Oakland',
        PlaceFIPSCode: '53000',
      },
    ],
  },
];
7
  • find() isn't async so no need to await. But .PlaceName exists on objects inside the cityObject.CountyPlaces array, so you'll need to iterate that array, probably with some() Commented Apr 8, 2023 at 23:02
  • You don't seem to be taking account of details.county, which it seems you should given that different counties may have places with the same name Commented Apr 8, 2023 at 23:05
  • Regarding async, this is just a portion of the larger code, and I guess I should have stripped that for example purposes here. Regarding place names, no, the data is structured so that counties do not have multiple places with the same name (although counties and places may have the same name). Commented Apr 8, 2023 at 23:08
  • Does this answer your question? ES6 - Finding data in nested arrays Commented Apr 8, 2023 at 23:09
  • 1
    Then you will need to filter as in Nick's answer below Commented Apr 9, 2023 at 0:02

2 Answers 2

1

You can filter the cities array based on the CountyName matching details.county[0], then filter the CountyPlaces of the matching city based on the PlaceName being in details.place:

const feeds = [
  {
    feed: {
      record: '0002',
      details: {
        county: ['Alameda'],
        place: ['Alameda', 'Berkeley', 'Oakland'],
      },
    },
  },
];

const cities = [
  {
    CountyName: 'San Francisco',
    CountyFIPSCode: '075',
    CountyPlaces: [
      {
        PlaceName: 'San Francisco', PlaceFIPSCode: '67000',
      },
    ],
  },
  {
    CountyName: 'Alameda',
    CountyFIPSCode: '001',
    CountyPlaces: [
      {
        PlaceName: 'Alameda', PlaceFIPSCode: '00562',
      },
      {
        PlaceName: 'Albany', PlaceFIPSCode: '00674',
      },
      {
        PlaceName: 'Berkeley', PlaceFIPSCode: '06000',
      },
      {
        PlaceName: 'Emeryville', PlaceFIPSCode: '22594',
      },
      {
        PlaceName: 'Oakland', PlaceFIPSCode: '53000',
      },
    ],
  },
];

const county = feeds[0].feed.details.county[0];
const places = feeds[0].feed.details.place;

const result = cities
  .filter(city => city.CountyName == county)[0]
  .CountyPlaces.filter(({ PlaceName }) => places.includes(PlaceName))
  
console.log(result)

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

6 Comments

Thank you very much for this answer! It was a toss-up as to which of the two suggested answers to accept (wish I could accept both). Your solution was clever and it hadn't occurred to me that I could key in on the matching counties first, then places (without using the outer map method for the "place" array). I'm sure I will lean on your solution in the future, since I will be working with this data many times in many different ways. Again, thanks.
@david No worries, I'm glad it was helpful. Note that if you want to use this code in a similar way to your question, you can just append a .forEach on the result objects e.g. .forEach(({ PlaceName, PlaceFIPSCode}) => { console.log(PlaceName); console.log(PlaceFIPSCode); }). In that scenario you would remove the const result = part of the code
Neat. So, chain the .forEach after the intial .filter. Still, without the outer .map. And it outputs individual property values rather than the "place" objects. That could come in handy. Thanks.
Ended up choosing your solution as the answer because it is more forgiving of the inconsistent data I am working with (a few of the feed.details.place property values are empty arrays, so I was getting errors as I noted in a comment on the other suggested answer here). Your code doesn't throw an error for the same data and it produces the output I need. Plus, your answer was a complete run-able code snippet. Much thanks!
@david I'm glad to hear this was a complete solution for you. Feel free to edit in the optional chaining into the answer if you want to, although obviously it's not required for the sample data.
|
1

If I understood your problem, can you try the following code;

const cityMatch = cities.find((cityObject, i) => {
    // console.log(i, 'cityObject: ', cityObject);
    return cityObject.CountyPlaces.some(p=>p.PlaceName===arrItem)
   
  });

getting only match place

const placeMatch = cityMatch.CountyPlaces.filter(p=>p.PlaceName===arrItem)[0]

3 Comments

Thanks. I like this solution, and it does return matches, but it's returning the entire county array for each result, when I need it to only return the specific matching place object for each.
For getting matched place, I think you can filter and grab the first index place as I had shown above.
Thanks for jumping back in with the follow up. This answer was the closest to my original code, and I appreciate that, but it keeps throwing an error, I think due to inconsistent data beyond my control (some feed.details.place property values are empty arrays). The error for the line const placeMatch = await cityMatch.CountyPlaces.filter((place) is "TypeError: Cannot read properties of undefined (reading 'CountyPlaces')". I tried optional chaining (?.) and a number of other things like if statements and could not solve the issue and still get the output I need.

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.