微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用JavaScript,如何将一个名称列表与来自相关数据项列表的聚合数据值进行映射?

如何解决使用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);

,

这种方法尽可能通用。它结合了mapreduce方法,从而使给定数据集(数据列表)和相应(目标)值列表中的任何数据 ,只需为上述 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;
},[]);


Output

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。