Предполагаемое решение должно быть доказательством общего подхода, основанного только на reduce
.
Основная идея - написать функцию редуктора многократного использования, которая использует свой первый аргумент accumulator
какобъект хранения, который содержит конфигурацию и результат этой конкретной задачи.Это также обогащает этот временно переданный объект как реестр, чтобы обеспечить быстрый поиск для лучшего обнаружения дубликатов элементов и строковых значений.
const data = [{
name: 'Lisa Simpson',
email: 'lisa@email.com',
favoriteSport: 'Soccer'
}, {
name: 'Lisa Simpson',
email: 'lisa@email.com',
favoriteSport: 'Tennis'
}, {
name: 'Lisa Simpson',
email: 'lisa@email.com',
favoriteSport: 'Swimming'
}, {
name: 'Lisa Simpson',
email: 'lisa@email.com',
favoriteSport: 'Voleyball'
}, {
name: 'Lisa Simpson',
email: 'lisa@email.com',
favoriteSport: 'Soccer'
}, {
name: 'Lisa Simpson',
email: 'lisa@email.com',
favoriteSport: 'Tennis'
}, {
name: 'Homer Simpson',
email: 'homer@email.com',
favoriteSport: 'Barbecuing'
}, {
name: 'Homer Simpson',
email: 'homer@email.com',
favoriteSport: 'TV marathoning'
}];
function concatSameItemStringValueByKeys(collector, item) {
const { assign } = Object;
const { samenessKey, concatKey, list } = collector;
const itemRegistry = (collector.itemRegistry || (collector.itemRegistry = {}));
const accessKey = item[samenessKey];
const stringValue = item[concatKey];
let registeredItem = itemRegistry[accessKey];
if (registeredItem) {
if (!(stringValue in registeredItem.valueRegistry)) { // - prevent item specific value duplicates.
registeredItem.valueRegistry[stringValue] = true;
registeredItem.type[concatKey].push(stringValue); // - concat item specific values.
}
} else {
registeredItem = itemRegistry[accessKey] = { // - create item specific registry.
type: assign({}, item), // - assign shallow item copy.
valueRegistry: {} // - create item specific value registry.
};
registeredItem.valueRegistry[stringValue] = true; // - prevent future item specific value duplicates.
registeredItem.type[concatKey] = [stringValue]; // - map item specific value initially to {Array}.
list.push(registeredItem.type); // - store the initially mapped+registered item additionally into a list.
}
return collector;
}
const reducedData = data.reduce(concatSameItemStringValueByKeys, {
samenessKey: 'email',
concatKey: 'favoriteSport',
list: []
}).list;
console.log('reducedData : ', reducedData);
.as-console-wrapper { max-height: 100%!important; top: 0; }
Подобную проблему / задачу теперь можно решить с помощью того же редуктора и другой стартовой конфигурации ...
const data = [{
id: 'xyz-abc',
value: 'foo'
}, {
id: 'xyz-abc',
value: 'bar'
}, {
id: 'ikl-mno',
value: 'foo'
}, {
id: 'ikl-mno',
value: 'bar'
}, {
id: 'xyz-abc',
value: 'baz'
}, {
id: 'xyz-abc',
value: 'biz'
}, {
id: 'ikl-mno',
value: 'foo'
}, {
id: 'ikl-mno',
value: 'bar'
}, {
id: 'xyz-abc',
value: 'foo'
}, {
id: 'xyz-abc',
value: 'bar'
}];
function concatSameItemStringValueByKeys(collector, item) {
const { assign } = Object;
const { samenessKey, concatKey, list } = collector;
const itemRegistry = (collector.itemRegistry || (collector.itemRegistry = {}));
const accessKey = item[samenessKey];
const stringValue = item[concatKey];
let registeredItem = itemRegistry[accessKey];
if (registeredItem) {
if (!(stringValue in registeredItem.valueRegistry)) { // - prevent item specific value duplicates.
registeredItem.valueRegistry[stringValue] = true;
registeredItem.type[concatKey].push(stringValue); // - concat item specific values.
}
} else {
registeredItem = itemRegistry[accessKey] = { // - create item specific registry.
type: assign({}, item), // - assign shallow item copy.
valueRegistry: {} // - create item specific value registry.
};
registeredItem.valueRegistry[stringValue] = true; // - prevent future item specific value duplicates.
registeredItem.type[concatKey] = [stringValue]; // - map item specific value initially to {Array}.
list.push(registeredItem.type); // - store the initially mapped+registered item additionally into a list.
}
return collector;
}
const reducedData = data.reduce(concatSameItemStringValueByKeys, {
samenessKey: 'id',
concatKey: 'value',
list: []
}).list;
console.log('reducedData : ', reducedData);
.as-console-wrapper { max-height: 100%!important; top: 0; }