0

Is there a way to compare an incomplete array to the source of truth array & return the missing elements? The array consists of objects & some of the objects have an array of objects.

let incompleteArr =[
          {
            "name": "Extra Toppings (Small)",
            "modifier_options": [{
                    "name": "Corn",
                    "price": 0.75
                },
                {
                    "name": "Extra mozzarella",
                    "price": 0.9
                },
                {
                    "name": "Onion",
                    "price": 0.45
                }
            ]
        },
        {
            "name": "Extra Toppings (Large)",
            "modifier_options": [{
                    "name": "Corn",
                    "price": 1.2
                },
                {
                    "name": "Extra Mozzarella",
                    "price": 1.7
                }
            ]
        }
    ]
  }]

  let completeArr =[
            {
                "name": "Extra Toppings (Small)",
                "modifier_options": [
                    {
                        "name": "Corn",
                        "price": 0.75
                    },
                    {
                        "name": "Extra mozzarella",
                        "price": 1.2
                    },
                    {
                        "name": "Extra Anchovies",
                        "price": 0.7
                    }
                ]
            },
            {
                "name": "Extra Toppings (Large)",
                "modifier_options": [
                    {
                        "name": "Corn",
                        "price": 1.2
                    },
                    {
                        "name": "Extra mozzarella",
                        "price": 1.7
                    }
                ]
            },
            {
                "name": "Extra Burger Toppings (Small)",
                "modifier_options": [
                    {
                        "name": "Extra Onion",
                        "price": 0.5
                    },
                    {
                        "name": "Extra Tomato",
                        "price": 0.55
                    },
                    {
                        "name": "Extra Cheese",
                        "price": 0.65
                    },
                    {
                        "name": "Extra Mayo",
                        "price": 0.3
                    },
                    {
                        "name": "Extra Patty",
                        "price": 2.5
                    }
                ]
            },
            {
                "name": "Extra Burger Toppings (Medium)",
                "modifier_options": [
                    {
                        "name": "Extra Onion",
                        "price": 0.6
                    },
                    {
                        "name": "Extra Tomato",
                        "price": 0.65
                    },
                    {
                        "name": "Extra Cheese",
                        "price": 0.75
                    },
                    {
                        "name": "Extra Mayo",
                        "price": 0.4
                    },
                    {
                        "name": "Extra Patty",
                        "price": 2.9
                    }
                ]
            },
            {
                "name": "Extra Burger Toppings (Large)",
                "modifier_options": [
                    {
                        "name": "Extra Onion",
                        "price": 0.8
                    },
                    {
                        "name": "Extra Tomato",
                        "price": 0.9
                    },
                    {
                        "name": "Extra Cheese",
                        "price": 0.95
                    },
                    {
                        "name": "Extra Mayo",
                        "price": 0.6
                    },
                    {
                        "name": "Extra Patty",
                        "price": 3.5
                    }
                ]
            }
        ]

Desired result is to return an array of missing elements. For example the "name" Extra Toppings (Small) must exist in the incompleteArr & the completeArr. Then the "modifier_options" must also be compared. Any modifier_options not in the incompleteArr must be pushed into the array of missing elements.

I have tried this so far

let missingMod = gfMods.filter(mod => lvMods.every(mod2 => !mod2.name.includes(mod.name)))

The output as expected is the missing items BUT I am not getting the missing nested array items from the modifier_options object. I have an idea that I need to loop through the arrays checking that the "names" exist & then a second loop to check if the modifier_options all exist. This is where I have been stuck.

[{
name:"Extra Burger Toppings (Small)",
modifier_options: [{
name:"Extra Onion",
price:0.5},
{name:"Extra Tomato",
price:0.55},
{name:"Extra Cheese",
price:0.65},
{name:"Extra Mayo",
price:0.3},
{name:"Extra Patty",
price:2.5}
]},
{name:"Extra Burger Toppings (Medium)",
modifier_options: [{
name:"Extra Onion",
price:0.6},
{name:"Extra Tomato",
price:0.65},
{name:"Extra Cheese",
price:0.75},
{name:"Extra Mayo",
price:0.4},
{name:"Extra Patty",
price:2.9}]
},
{name:"Extra Burger Toppings (Large)",
modifier_options: [{
name:"Extra Onion",
price:0.8},
{name:"Extra Tomato",
price:0.9},
{name:"Extra Cheese",
price:0.95},
{name:"Extra Mayo",
price:0.6},
{name:"Extra Patty",
price:3.5}]
}]
1
  • What do lvMods and gfMods refer to respectively? Commented Jan 8, 2022 at 5:26

1 Answer 1

1

This solution utilizes the .reduce(), .find(), .some(), and .filter() Array methods.

// Reduces the complete array, to a list of missing values from
// the incomplete array.
const result = completeArr.reduce((prev, next) => {
  // Finds whether the object exists in the incomplete array.
  // _main will hold the matching object from the incomplete
  // array if found, or undefined otherwise.
  const _main = incompleteArr.find(obj => obj.name == next.name);
  
  // If it does find, stop here and check for missing
  // values inside modifier options.
  if(_main){
    // .filter to get the missing modifier objects from the 
    // incomplete array. Done by checking if a
    // modifier option of the complete array 
    // is NOT present in the incomplete array's
    // modifier options list.
    const _mod = next.modifier_options.filter(next_mod => !_main.modifier_options.some(main_mod => next_mod.name == main_mod.name));
    
    // Add _mod(containing missing modifier options) to
    // the accumulating array and return.
    return [...prev, {parent: next.name, modifier_options: _mod}];
  }
  
  // This next object doesn't exist in the incomplete 
  // array as it wasn't found, so add it to the accumulating
  // list of missing items.
  return [...prev, next];
}, []);

let incompleteArr = [
      {
        "name": "Extra Toppings (Small)",
        "modifier_options": [{
                "name": "Corn",
                "price": 0.75
            },
            {
                "name": "Extra mozzarella",
                "price": 0.9
            },
            {
                "name": "Onion",
                "price": 0.45
            }
        ]
    },
    {
        "name": "Extra Toppings (Large)",
        "modifier_options": [{
                "name": "Corn",
                "price": 1.2
            },
            {
                "name": "Extra Mozzarella",
                "price": 1.7
            }
        ]
    }
];

let completeArr = [
    {
        "name": "Extra Toppings (Small)",
        "modifier_options": [
            {
                "name": "Corn",
                "price": 0.75
            },
            {
                "name": "Extra mozzarella",
                "price": 1.2
            },
            {
                "name": "Extra Anchovies",
                "price": 0.7
            }
        ]
    },
    {
        "name": "Extra Toppings (Large)",
        "modifier_options": [
            {
                "name": "Corn",
                "price": 1.2
            },
            {
                "name": "Extra mozzarella",
                "price": 1.7
            }
        ]
    },
    {
        "name": "Extra Burger Toppings (Small)",
        "modifier_options": [
            {
                "name": "Extra Onion",
                "price": 0.5
            },
            {
                "name": "Extra Tomato",
                "price": 0.55
            },
            {
                "name": "Extra Cheese",
                "price": 0.65
            },
            {
                "name": "Extra Mayo",
                "price": 0.3
            },
            {
                "name": "Extra Patty",
                "price": 2.5
            }
        ]
    },
    {
        "name": "Extra Burger Toppings (Medium)",
        "modifier_options": [
            {
                "name": "Extra Onion",
                "price": 0.6
            },
            {
                "name": "Extra Tomato",
                "price": 0.65
            },
            {
                "name": "Extra Cheese",
                "price": 0.75
            },
            {
                "name": "Extra Mayo",
                "price": 0.4
            },
            {
                "name": "Extra Patty",
                "price": 2.9
            }
        ]
    },
    {
        "name": "Extra Burger Toppings (Large)",
        "modifier_options": [
            {
                "name": "Extra Onion",
                "price": 0.8
            },
            {
                "name": "Extra Tomato",
                "price": 0.9
            },
            {
                "name": "Extra Cheese",
                "price": 0.95
            },
            {
                "name": "Extra Mayo",
                "price": 0.6
            },
            {
                "name": "Extra Patty",
                "price": 3.5
            }
        ]
    }
];

const result = completeArr.reduce((prev, next) => {
  const _main = incompleteArr.find(obj => obj.name == next.name);
  if(_main){
    const _mod = next.modifier_options.filter(next_mod => !_main.modifier_options.some(main_mod => next_mod.name == main_mod.name));
    return [...prev, {parent: next.name, modifier_options: _mod}];
  }
  return [...prev, next];
}, []);

console.log(result);

Note: It'll return "Extra mozzarella" from "Extra Toppings (Large)" because of the case difference. Also, forgive the poor variable names, I hope this solution solves your problem.

Update

As per the request of OP, I added the .name of the parent object the missing modifier_options belong to.

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

5 Comments

Hi Vektor, thanks for the answer. It is almost perfect. I just need to be able to output the "name" of the object the missing item belongs to. So the "Extra Anchovies" is the missing "modifier_option" of the object "Extra Toppings (Small). Unfortunately in the missing items returned we don't get that level info returned. we only get the modifier option.
@BradLegassick I added it in.
Hi Vektor thanks mate you're a champ! So far so good. I appreciate your help with this solution. If you have a link to any docs for me to read up on the solution implemented I would appreciate it. Cheers
I came up with the solution, but I can document the code and include details in my post about the process.
Thanks mate, that would be awesome if you get a chance. Cheers

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.