1

I'm having trouble narrowing my filter down to the specific object I need in my JSON.

JSON:

var items = {
    "itemsGroup": [
        {
            "item": [
                {"description": "Name", "value": "Jane Doe"},
                {"description": "Age", "value": 23},
                {"description": "Phone", "value": "515-555-1234"},
                {"description": "Address", "value": "123 Fake St"},
                {"description": "City", "value": "Winchestertonfieldville"},
                {"description": "State", "value": "IA"},
                {"description": "Zip", "value": 50000}
            ],
        },
        {
            "item": [
                {"description": "Eye Color", "value": "Blue"},
                {"description": "Hair", "value": "Blonde"},
                {"description": "Height", "value": "5'6"},
                {"description": "Weight", "value": 125}
            ]
        }
    ]
}

I want the object containing Name in the first nested array:

{"description": "Name", "value": "Jane Doe"}

I can achieve that like this:

_.findWhere(items.itemsGroup[0].item, {description:'Name'})

But I want to account for the case where the JSON could change.

The closest I've gotten is with this underscore function:

_.filter(items.itemsGroup, function(i) {
    return _.findWhere(i.item, {description:'Name'});
});

But that returns the entire first nested array rather than the object I'm looking for (as in my first example).

"item": [
    {"description": "Name", "value": "Jane Doe"},
    {"description": "Age", "value": 23},
    {"description": "Phone", "value": "515-555-1234"},
    {"description": "Address", "value": "123 Fake St"},
    {"description": "City", "value": "Winchestertonfieldville"},
    {"description": "State", "value": "IA"},
    {"description": "Zip", "value": 50000}
]

What can I try next?

halfer
  • 19,824
  • 17
  • 99
  • 186
Great Scott
  • 1,325
  • 15
  • 22
  • i had faced similar problem before, and i think i have an answer but i'm not good in english so i think i didn't understand your problem well, can you explain simply your problem and what do you want. sorry about that – Pooya Behravesh Apr 16 '20 at 19:43

2 Answers2

0

"itemsGroup"s content is array, so you can iterate that array.

const items = {
    "itemsGroup": [
        {
            "item": [
                {"description": "Name", "value": "Jane Doe"},
                {"description": "Age", "value": 23},
                {"description": "Phone", "value": "515-555-1234"},
                {"description": "Address", "value": "123 Fake St"},
                {"description": "City", "value": "Winchestertonfieldville"},
                {"description": "State", "value": "IA"},
                {"description": "Zip", "value": 50000}
            ],
        },
        {
            "item": [
                {"description": "Eye Color", "value": "Blue"},
                {"description": "Hair", "value": "Blonde"},
                {"description": "Height", "value": "5'6"},
                {"description": "Weight", "value": 125}
            ]
        }
    ]
}

const { itemsGroup } = items;

itemsGroup.map((itemGroup) => {
  return _.findWhere(itemGroup.item, {description:'Name'})
});

Not the optional solution, but it will do the trick i guess.

redempt
  • 51
  • 1
  • 2
0

All the information you're interested in is in items.itemsGroup, so we start by simply extracting that property. We put this in a chain, so we can massage the data into the shape we want step by step.

_.chain(items.itemsGroup).value();
// [ { item: [ ... ] },
//   { item: [ ... ] } ]

This is an array of objects. In each object, we're only interest in the item property, so our next step could be to take out just that property.

_.chain(items.itemsGroup).map('item').value();
// [ [ { description: 'Name', value: 'Jane Doe' },
//     { description: 'Age', value: 23 },
//     { description: 'Phone', value: '515-555-1234' },
//     { description: 'Address', value: '123 Fake St' },
//     { description: 'City', value: 'Winchestertonfieldville' },
//     { description: 'State', value: 'IA' },
//     { description: 'Zip', value: 50000 } ],
//   [ { description: 'Eye Color', value: 'Blue' },
//     { description: 'Hair', value: 'Blonde' },
//     { description: 'Height', value: '5\'6' },
//     { description: 'Weight', value: 125 } ] ]

Now we have an array of arrays, with each element in the innermost arrays being a { description, value } pair. Since we simply want the first such pair that has { description: 'Name' }, the nesting of the arrays does not actually matter to us. We can remove the intermediate level of nesting to simplify our lives.

_.chain(items.itemsGroup).map('item').flatten().value();
// [ { description: 'Name', value: 'Jane Doe' },
//   { description: 'Age', value: 23 },
//   { description: 'Phone', value: '515-555-1234' },
//   { description: 'Address', value: '123 Fake St' },
//   { description: 'City', value: 'Winchestertonfieldville' },
//   { description: 'State', value: 'IA' },
//   { description: 'Zip', value: 50000 },
//   { description: 'Eye Color', value: 'Blue' },
//   { description: 'Hair', value: 'Blonde' },
//   { description: 'Height', value: '5\'6' },
//   { description: 'Weight', value: 125 } ]

Now it's just a matter of taking out that first matching { description, value } pair.

_.chain(items.itemsGroup).map('item').flatten()
 .findWhere({ description: 'Name' }).value();
// { description: 'Name', value: 'Jane Doe' }

For a more thorough introduction to decomposing logic with Underscore functions, see this answer.

Julian
  • 4,176
  • 19
  • 40