如何解决使用JavaScript,如何将一个名称列表与来自相关数据项列表的聚合数据值进行映射?
也许有人可以给我一个主意,我该怎么做。因此,我有一组名称["Tom","Jane","Mike","John"]
,还有一组对象是购买报告:
[
{ date: "19/02/2019",name: "Mike",amount: 10 },{ date: "20/02/2019",amount: 15 },{ date: "21/10/2019",name: "Jane",amount: 25 },{ date: "22/03/2019",name: "John",amount: 30 },{ date: "19/03/2019",name: "Tom",amount: 15 }
]
我需要获得代表一个人的物品及其总花费额。 [{ name: "Tom",{ name: "Mike",...
我希望你明白。我该如何实现?我尝试map
对象的名称和过滤器数组,但得到undefined
。
解决方法
结合使用map,filter和reduce来整理数据:
第一个.map正在构建对象结构,例如{name: '...',amount: <val>}
为了获取每个名称的值,您可以按名称过滤支出,并通过添加来减少输出值。
const names = ["Tom","Jane","Mike","John"];
const spendings = [{
date: "19/02/2019",name: "Mike",amount: 10
},{
date: "20/02/2019",amount: 15
},{
date: "21/10/2019",name: "Jane",amount: 25
},{
date: "22/03/2019",name: "John",amount: 30
},{
date: "19/03/2019",name: "Tom",amount: 15
}];
const result = names.map(name => {
return {
name,amount: spendings.filter(spending => spending.name === name).reduce((sum,{
amount
}) => sum + amount,0)
};
});
console.log(result);
,
您可以尝试以下代码:
const data = [
{ date: "19/02/2019",amount: 10 },{ date: "20/02/2019",amount: 15 },{ date: "21/10/2019",amount: 25 },{ date: "22/03/2019",amount: 30 },{ date: "19/03/2019",];
const names = ["Tom","John"];
const results = names.map((name) => ({
name,amount: data
.filter(({ name: dataName }) => dataName === name)
.reduce((total,{ amount }) => total + amount,0),}));
console.log(results);
.as-console-wrapper { min-height: 100%!important; top: 0; }
,
在报表数组上使用 Array.reduce 。
然后将报告数组简化为每个名称的总报告字典。
请先尝试自行解决。
这是我的解决方案:
const dictionaryReports = reports.reduce((prev,curr)=>{
if(!prev[curr.name]) {
return {...prev,prev[curr.name] : curr}
}else{
return {
...prev,prev[curr.name]:
{
...prev[curr.name],amount : prev[curr.name].amount + curr.amount
}
}
}
},{})
输出将是:
dictionaryReports = {
Mike : {name:"Mike",amount:25},Tom : {name:"Tom",amount:15}
}
那么你可以做
Object.values(dictionaryReports)
,
您可以根据需要使用javascript过滤器方法进行设置。
例如。如果要在数组中获取与名称和数量匹配的条目,可以编写如下函数:
const result = (name,cost) => array.filter(customer => {
return name == customer.name && cost == customer.cost;
});
运行结果(“简”,25)将返回以下内容:
[{date: "21/10/2019",amount: 25}]
,
您可以使用所需名称创建一个对象,然后将金额添加到每个属性中。
const
names = ["Tom","John"],purchases = [{ date:"19/02/2019",amount: 15 }],result = purchases.reduce(
(object,{ name,amount }) => (object[name] += amount,object),Object.fromEntries(names.map(name => [name,0]))
);
console.log(result);
,
这种方法尽可能通用。它结合了map
和reduce
方法,从而使给定数据集(数据列表)和相应(目标)值列表中的任何数据 ,只需为上述 map-reduce 组合提供开始配置即可
const dataset = [
{ date: "19/03/2019",name: "Jerry",amount: 45 },{ date: "19/02/2019",amount: 15 }
];
function aggregateTargetItemValueFromSourceKey(collector,item) {
const { aggregateValue,sourceKey,targetKey,targetItem } = collector;
if (targetItem[targetKey] === item[targetKey]) {
targetItem[sourceKey] = aggregateValue(targetItem[sourceKey],item[sourceKey]);
}
return collector;
}
function createTargetItemFromBoundDatasetConfig(targetValue) {
const { dataset,aggregateValue,initialValue,targetKey } = this;
return dataset.reduce(aggregateTargetItemValueFromSourceKey,{
aggregateValue,targetItem: {
[targetKey]: targetValue,[sourceKey]: initialValue
}
}).targetItem;
}
console.log(
["Tom","John"]
.map(createTargetItemFromBoundDatasetConfig,{
aggregateValue: ((targetValue,sourceValue) => targetValue + sourceValue),initialValue: 0,sourceKey: 'amount',targetKey: 'name',dataset
})
);
console.log(
[5,10,15,20,25,30,35,40,45,50]
.map(createTargetItemFromBoundDatasetConfig,sourceValue) => targetValue.concat(sourceValue)),initialValue: [],sourceKey: 'name',targetKey: 'amount',dataset
})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
第二种方法很简单,因此它产生的结果灵活性较差。不过,至少可以选择从提供的数据集中的任何项目中简单地聚合数据,或者,正如所提供的名称列表无意中暗示了OP,可以使用后者仅过滤数据集中的那些项目。实际上是其名称之一。 ...
const dataset = [
{ date: "19/03/2019",amount: 15 }
];
const itemNameList = ["Tom","John"];
function aggregateItemAmountByItemNameWithOptionalNameCeck(collector,item) {
const { checklist,index,list } = collector;
const itemName = item.name;
const isProceed = (!Array.isArray(checklist) || checklist.includes(itemName))
if (isProceed) {
let targetItem = index[itemName];
if (!targetItem) {
targetItem = index[itemName] = {
name: itemName,amount: 0
};
list.push(targetItem);
}
targetItem.amount = targetItem.amount + item.amount;
}
return collector;
}
console.log(
'with name check ... ',dataset.reduce(aggregateItemAmountByItemNameWithOptionalNameCeck,{
checklist: itemNameList,index: {},list: []
}).list
);
console.log(
'without name check ... ',{
index: {},list: []
}).list
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
,
您可以在购买时使用数组减少方法。您不需要名称数组,我认为它对结果看起来毫无用处。
const purchases = [
{ date: "19/02/2019",amount: 15 }
]
const overall = purchases.reduce((acc,curr) => {
const currentUser = acc.find(x => x.name === curr.name);
if(currentUser) {
currentUser.amount += curr.amount;
} else {
acc.push({name:curr.name,amount: curr.amount})
}
return acc;
},[]);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。