JavaScript中如何根据对象嵌套属性过滤数组?
Great job on the basic array filtering function! Let's expand it to handle nested object properties smoothly, just like you need. We'll make it support both string property paths (e.g., 'd.id') and array paths (e.g., ['d','id']), and it’ll work for any depth of nesting.
Step 1: Normalize the Property Path
First, we need to convert any incoming path (string or array) into a consistent array format. This way, we can easily traverse nested properties regardless of how the path is passed in.
Step 2: Safely Retrieve Nested Values
We’ll build a helper function to get the value from a nested object using the path array. This function will avoid runtime errors if a property in the path doesn’t exist (it’ll just return undefined instead).
Step 3: Update the Filter Function
Now we’ll modify your list_filter function to use these utilities, letting it filter based on nested properties.
Full Implementation Code
// Helper to convert path to standard array format function normalizePath(path) { if (Array.isArray(path)) { return path; } // Split string paths by dots, ignore empty parts from accidental leading/trailing dots return path.split('.').filter(part => part.trim() !== ''); } // Helper to safely get nested value from an object function getNestedValue(obj, path) { let current = obj; for (const key of path) { // Stop and return undefined if we hit a null/undefined or missing property if (current == null || !(key in current)) { return undefined; } current = current[key]; } return current; } // Extended filter function for nested properties function list_filter(arr, path, targetValue) { const normalizedPath = normalizePath(path); return arr.filter(item => { const nestedValue = getNestedValue(item, normalizedPath); return nestedValue === targetValue; }); } // Test with your sample array var a = [ {a:'1', b:"2", c:3, d: {id:'d1'}}, {a:'1', b:"2", c:3, d: {id:'d2'}}, {a:'1', b:"2", c:3, d: {id:'d1'}}, {a:'1', b:"2", c:3, d: {id:'d3'}}, {a:'1', b:"2", c:3, d: {id:'d3'}}, {a:'1', b:"2", c:3, d: {id:'d4'}} ]; // Test with array path console.log(list_filter(a, ['d', 'id'], 'd1')); // Output: [{a:'1', b:"2", c:3, d: {id:'d1'}}, {a:'1', b:"2", c:3, d: {id:'d1'}}] // Test with string path console.log(list_filter(a, 'd.id', 'd3')); // Output: [{a:'1', b:"2", c:3, d: {id:'d3'}}, {a:'1', b:"2", c:3, d: {id:'d3'}}] // Test with deeper nesting (example) const deepArray = [ {x: {y: {z: 'foo'}}}, {x: {y: {z: 'bar'}}}, {x: {y: {z: 'foo'}}} ]; console.log(list_filter(deepArray, ['x', 'y', 'z'], 'foo')); // Output: [{x: {y: {z: 'foo'}}}, {x: {y: {z: 'foo'}}}]
How It Works
normalizePath: Takes either a string or array path and returns a clean array of property keys. It handles edge cases like accidental leading/trailing dots by filtering out empty parts.getNestedValue: Traverses the object step by step using the path array. If any step hits anull/undefinedor missing property, it returnsundefinedto avoid crashes.list_filter: Uses the normalized path to fetch each item’s nested value, then filters the array to keep only items where this value matches your target.
Edge Cases Handled
- Paths that don’t exist in some items: Those items will return
undefined, so they won’t match any target value (unless you’re explicitly filtering forundefined). - Mixed path formats: Both string and array paths work interchangeably.
- Any depth of nesting: Works for paths like
['a','b','c','d']just as well as shallow paths.
内容的提问来源于stack exchange,提问作者qg_java_17137

