如何用ES6的map与reduce统计两数组总元素及name字段匹配/不匹配数
Hey there! Let's walk through how to solve this using ES6's map and reduce methods—they're perfect for this kind of data transformation and aggregation.
First, let's clarify the requirements to make sure we're on the same page:
- Total elements: Simple sum of the lengths of arrays A and B
- Matched elements: Count of items where the
nameexists in the other array (e.g., an item in A counts as matched if itsnameappears in B, and vice versa) - Unmatched elements: Total elements minus matched elements
Here's a step-by-step implementation with explanations:
Step 1: Create fast-lookup sets of names from each array
We'll use map to extract all name values from each array, then store them in Set objects for O(1) lookups (way faster than checking arrays directly):
const arrayA = [{ name: "Alice" }, { name: "Bob" }, { name: "Charlie" }]; const arrayB = [{ name: "Bob" }, { name: "Dave" }, { name: "Eve" }]; // Extract names from each array using map, then store in Sets const namesInA = new Set(arrayA.map(item => item.name)); const namesInB = new Set(arrayB.map(item => item.name));
Step 2: Mark each element as matched or not
Use map again to convert every element in both arrays into a boolean flag indicating if its name exists in the other array. We'll combine these flags into a single array for easy aggregation:
// Mark elements in A: does their name exist in B? const matchedFlagsA = arrayA.map(item => namesInB.has(item.name)); // Mark elements in B: does their name exist in A? const matchedFlagsB = arrayB.map(item => namesInA.has(item.name)); // Combine both flag arrays const allFlags = [...matchedFlagsA, ...matchedFlagsB];
Step 3: Aggregate stats with reduce
Now use reduce to iterate over the flag array and calculate our three values. We'll start with an accumulator object that tracks total, matched, and unmatched counts:
const stats = allFlags.reduce((acc, isMatched) => { acc.total += 1; isMatched ? acc.matched += 1 : acc.unmatched += 1; return acc; }, { total: 0, matched: 0, unmatched: 0 }); console.log(stats); // Output: { total: 6, matched: 2, unmatched: 4 }
How it works:
mapshines here for transforming data: first extracting names, then creating match flags. It keeps our code clean and declarative.reduceis perfect for aggregating the flags into a single stats object—we build up our counts incrementally with each iteration.- Using
Setensures our lookups are efficient, which is especially helpful if your arrays are large.
If you want to make it more concise (though readability might suffer a bit), you can combine some steps:
const stats = [ ...arrayA.map(item => new Set(arrayB.map(b => b.name)).has(item.name)), ...arrayB.map(item => new Set(arrayA.map(a => a.name)).has(item.name)) ].reduce((acc, isMatched) => { acc.total++; acc[isMatched ? 'matched' : 'unmatched']++; return acc; }, { total: 0, matched: 0, unmatched: 0 });
But I recommend the first approach—separating concerns makes it easier to debug and modify later.
内容的提问来源于stack exchange,提问作者Bonnard

