JavaScript算法挑战:实现匹配指定键值对的对象筛选函数
I need to write a function that takes two parameters: the first is an array of objects, the second is a source object. The function should return all objects in the array that contain all key-value pairs from the source object.
For example, if the first parameter is
[{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }]and the second is{ last: "Capulet" }, the function should return the third object since it includes the passed key-value pair.
My Attempted Code
function whatIsInAName(collection, source) { let filteredCollection = collection.filter((item)=>{ return collection[item].indexOf((source[item])> 0); }) return filteredCollection; } whatIsInAName([{ first: "Romeo", last: "Montague" }, { first: "Tybalt", last: "Capulet" }], { last: "Capulet" });
My Problem
I'm having trouble iterating through the objects and checking for the relevant key-value pairs at the same time. It seems like some array methods don't work directly on objects. Could someone help me fix this code?
Solution & Explanation
Let's start by clearing up the issues in your current code:
collection[item]is incorrect—itemis already an object from the collection array, so you don't need to index into the collection with it.indexOf()is an array method, not something you can use to check object key-value pairs.- You weren't actually verifying that every key-value pair from the source exists in the target object.
Here's a fixed, working version of your function:
function whatIsInAName(collection, source) { // Grab all the keys from the source object to check against const sourceKeys = Object.keys(source); // Filter the collection to keep only matching objects return collection.filter(item => { // Make sure every key in the source matches the item's key-value pair return sourceKeys.every(key => { // Check the item has the key, and its value matches the source's return item.hasOwnProperty(key) && item[key] === source[key]; }); }); } // Test with your example console.log(whatIsInAName([{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }], { last: "Capulet" })); // Output: [{ first: "Tybalt", last: "Capulet" }]
Let's break down how this works step by step:
Object.keys(source)creates an array of all keys in the source object (like["last"]in your example).collection.filter()loops through each object in the input array.- For each object,
sourceKeys.every()ensures all source keys pass two checks:- The object actually has the key (using
hasOwnPropertyto avoid inherited properties—optional but safe practice). - The value of that key in the object exactly matches the value in the source.
- The object actually has the key (using
- Only objects that pass all these checks stay in the final filtered array.
If you prefer a more concise version (using arrow function shorthand), this works too:
function whatIsInAName(collection, source) { const sourceKeys = Object.keys(source); return collection.filter(item => sourceKeys.every(key => item[key] === source[key])); }
This shorter version omits hasOwnProperty—it still works for most cases, since if the item doesn't have the key, item[key] will be undefined, which won't match the source's value (unless the source's value is also undefined, but you can add back hasOwnProperty if you need to handle that edge case).
内容的提问来源于stack exchange,提问作者AndrewNeedsHelp

