通过键减少转换单个数组

Posted

技术标签:

【中文标题】通过键减少转换单个数组【英文标题】:Transform single an array with reduce by key 【发布时间】:2021-12-30 04:17:03 【问题描述】:

我在这里Transform an Array into an Object using .reduce() 提出了类似的问题,但是我正在尝试使用 findIndex 找到替代解决方案。

这个输入数据:

const reports = [
  
    dateOfReport: "11-01-2021",
    userId: "id1",
    userMetric:  first_metric: 10, second_metric: 15 ,
  ,
  
    dateOfReport: "11-01-2021",
    userId: "id2",
    userMetric:  first_metric: 9, second_metric: 14 ,
  ,
  
    dateOfReport: "12-01-2021",
    userId: "id1",
    userMetric:  first_metric: 11, second_metric: 14 ,
  ,
  
    dateOfReport: "12-01-2021",
    userId: "id2",
    userMetric:  first_metric: 16, second_metric: 19 ,
  ,
];

输出数据必须是:

const output = [
  
    dateOfReport: "11-01-2021",
    id1:  first_metric: 10, second_metric: 15 ,
    id2:  first_metric: 9, second_metric: 14 ,
  ,
  
    dateOfReport: "12-01-2021",
    id1:  first_metric: 11, second_metric: 14 ,
    id2:  first_metric: 16, second_metric: 19 ,
  ,
];

我尝试在下面编写类似的代码,但输出中出现重复数据。谁能帮忙解决这个问题?

const groupedReports = reports.reduce((acc, dataItem) => 
    const nodeIndex = acc.findIndex((item) => item.dateOfReport === dataItem.dateOfReport);
    const newNode =  date: dataItem.date, [dataItem.userId]: dataItem.userMetric ;

    console.log("NEW NODE", newNode);

    return [...acc.slice(0, nodeIndex - 1), newNode, ...acc.slice(nodeIndex + 1)]
  , []);

【问题讨论】:

【参考方案1】:

您可以使用一个对象进行分组并将新属性分配给 id。

const
    reports = [ dateOfReport: "11-01-2021", userId: "id1", userMetric:  first_metric: 10, second_metric: 15  ,  dateOfReport: "11-01-2021", userId: "id2", userMetric:  first_metric: 9, second_metric: 14  ,  dateOfReport: "12-01-2021", userId: "id1", userMetric:  first_metric: 11, second_metric: 14  ,  dateOfReport: "12-01-2021", userId: "id2", userMetric:  first_metric: 16, second_metric: 19  ],
    result = Object.values(reports.reduce((r,  dateOfReport, userId, userMetric ) => 
        (r[dateOfReport] ??=  dateOfReport )[userId] = userMetric;
        return r;
    , ));

console.log(result);
.as-console-wrapper  max-height: 100% !important; top: 0; 

【讨论】:

//(r[dateOfReport] ??= dateOfReport )[userId] = userMetric;据我了解,此解决方案会改变对象而不是创建新对象 这个属性赋值有什么问题?【参考方案2】:

我认为你可以这样做:

reports.reduce((pre, cur) => 
    let index = pre.findIndex(item => item.dateOfReport == cur.dateOfReport)
    if (index != -1) 
        pre[index][cur.userId] = cur.userMetric
     else 
        pre.push(
            dateOfReport: cur.dateOfReport,
            [cur.userId]: cur.userMetric
        )
    
    return pre
, [])

【讨论】:

我注意到你的代码使用了slice,它消耗了太多的性能。【参考方案3】:

这是我的解决方案:

const reports = [
  
    dateOfReport: "11-01-2021",
    userId: "id1",
    userMetric:  first_metric: 10, second_metric: 15 ,
  ,
  
    dateOfReport: "11-01-2021",
    userId: "id2",
    userMetric:  first_metric: 9, second_metric: 14 ,
  ,
  
    dateOfReport: "12-01-2021",
    userId: "id1",
    userMetric:  first_metric: 11, second_metric: 14 ,
  ,
  
    dateOfReport: "12-01-2021",
    userId: "id2",
    userMetric:  first_metric: 16, second_metric: 19 ,
  ,
];

const sortReports = (reports) => 
    // Array of dates with no duplicates
    const dates = [...new Set(reports.map(el => el.dateOfReport))];
    // Replace each date with an array of reports that are relevant to the date
    // Reduce each array of reports into an object with your desired format
    const newReports = dates
      .map(date => reports
      .filter(report => report.dateOfReport === date)
      .reduce(el => (
        dateOfReport: el.dateOfReport,
        [el.userId]: el.userMetric
      )));
    return newReports;

  
console.log(sortReports(reports));

【讨论】:

以上是关于通过键减少转换单个数组的主要内容,如果未能解决你的问题,请参考以下文章

PHP在连接键时将嵌套数组转换为单个数组?

通过键减少数组对象并返回嵌套对象

通过具有日期值的单个键对对象数组进行排序

将数组的并行流减少为单个数组

尝试使用 AJAX 在 Laravel 中上传单个文件时出现数组到字符串转换错误

Swift - 使用 map/reduce/flatmap 将数组字典减少为相同类型的单个数组