Techniques for Filtering, Deduplicating, and Grouping Data in JavaScript
Considre an array of objects representing data entries:
const dataEntries = [
{ id: 1, city: 'Dalian1', year: 2023 },
{ id: 2, city: 'Dalian2', year: 2025 },
{ id: 3, city: 'Dalian3', year: 2023 },
{ id: 4, city: 'Dalian4', year: 2027 },
{ id: 5, city: 'Dalian5', year: 2023 },
{ id: 6, city: 'Dalian6', year: 2023 },
{ id: 7, city: 'Dalian Road', year: 2023 }
];
Extracting Unique Years
To obtain a list of distinct years present in the dataset, utilize a Set for automatic deduplication:
const uniqueYearsSet = new Set(dataEntries.map(entry => entry.year));
console.log('Unique Years (Set):', uniqueYearsSet);
Convert the Set to an array for a more conventional list format:
const uniqueYearsArray = [...new Set(dataEntries.map(entry => entry.year))];
console.log('Unique Years (Array):', uniqueYearsArray);
Retrieving the First Entry per Year
Method 1: Using reduce with an Auxiliary Array
Track encountered years with a separate array to filter for first occurrences.
const encounteredYears = [];
const firstEntries = dataEntries.reduce((accumulator, currentEntry) => {
if (!encounteredYears.includes(currentEntry.year)) {
accumulator.push(currentEntry);
encounteredYears.push(currentEntry.year);
}
return accumulator;
}, []);
console.log('First Entries per Year (reduce + includes):', firstEntries);
Method 2: Using forEach with some
Iterate through the array, adding entries only if their year hasn't been recorded yet.
const firstEntriesList = [];
dataEntries.forEach(entry => {
if (!firstEntriesList.some(existing => existing.year === entry.year)) {
firstEntriesList.push(entry);
}
});
console.log('First Entries per Year (forEach + some):', firstEntriesList);
Method 3: Using reduce with find
Check for the existence of the year directly within the acumulator array.
const initialEntries = dataEntries.reduce((acc, entry) => {
if (!acc.find(existing => existing.year === entry.year)) {
acc.push(entry);
}
return acc;
}, []);
console.log('First Entries per Year (reduce + find):', initialEntries);
Grouping Entries by Year
Method 1: reduce with an Auxiliary Array
Build an object where keys are years and values are arrays of entries for that year.
const yearTracker = [];
const groupedByYear = dataEntries.reduce((grouping, entry) => {
if (!yearTracker.includes(entry.year)) {
grouping[entry.year] = [entry];
yearTracker.push(entry.year);
} else {
grouping[entry.year].push(entry);
}
return grouping;
}, {});
console.log('Grouped by Year (reduce + includes):', groupedByYear);
Method 2: forEach with an Auxiliary Array
Similar logic implemented using forEach for iteration.
const seenYears = [];
const yearGroups = {};
dataEntries.forEach(entry => {
if (!seenYears.includes(entry.year)) {
yearGroups[entry.year] = [entry];
seenYears.push(entry.year);
} else {
yearGroups[entry.year].push(entry);
}
});
console.log('Grouped by Year (forEach + includes):', yearGroups);
Method 3: reduce with the in Operator
Use the in operator to check for the existance of a year key in the accumulator object.
const groupedData = dataEntries.reduce((acc, entry) => {
if (entry.year in acc) {
acc[entry.year].push(entry);
} else {
acc[entry.year] = [entry];
}
return acc;
}, {});
console.log('Grouped by Year (reduce + in):', groupedData);