使用相同的键动态合并对象数组并将其创建为新数据(对象数组)

Merge array of object dynamically with same key and create it as new data (array of object)

我有一些对象数组 我想用相同的键合并对象数组,并根据键和值将其创建为新对象

const data =[{
  date:"19",
  status:"in",
hour:”12:00”

},{

  date:"19",
  status:"in",
hour:”12:20”
},{
  date:"19",
  status:"in",
hour:”12:43”
},{
  date:"19",
  status:"out",
hour:”16:16”

},{
  date:"20",
  status:"in",
hour:07:30”
},{
  date:"20",
  status:"out",
hour:”14:40”
},{
  date:"21",
  status:"in",
hour:”08:12”
}
]

这是我想要的结果


result =[{
date:”19”,
hourIn= “12:00”,
hourOut= “16:16”,      
}, {
  date:"20",
  hourIn:"07:30",
hourOut:14:40”
},{
  date:"21",
hourIn:”08:12”,
hourOut:”-“}]

我想如何解决这个问题?

您正在尝试实现一个小型 MapReduce。您可以google了解更多详情。

  1. 创建一个地图,其中键是您的日期,值是具有相同日期的对象数组。

  2. 现在通过将所有对象插入地图来按日期分隔所有对象。

  3. 以输入、输出为第一条件,时间为第二条件对数组进行排序。所以在每个数组中,第一个对象将是时间上的第一个,最后一个对象将是最后一个时间。

  4. 将每个数组缩减为一个对象取第一个和最后一个对象。

    let map = new Map();

    for(让d的数据){ 让 t = map.get(d.date)||[]; t.push(d); map.set(d.date,t); }

    for(让 v of map.values()){ v.sort((a,b)=>a.status < b.status || timecmp(a.hour,b.hour)) // 实现 timecmp }

    让结果=[]

    for(让 v of map.values()){ let reduced = // 从 v[0] v[v.length-1] 中获取 结果t.push(减少); }

这是我的做法, 我遍历了 data,检查该日期是否已经过去。

如果不是,我检查了statusin还是out,然后设置hourdate

如果通过了,我检查了status,然后检查时间是早于hourIn还是晚于已经设置的hourOut

let result={};
const data=[{date:"19",status:"in",hour:"12: 00"},{date:"19",status:"in",hour:"12:20"},{date:"19",status:"in",hour:"12:43"},{date:"19",status:"out",hour:"16:16"},{date:"20",status:"in",hour:"07:30"},{date:"20",status:"out",hour:"14:40"},{date:"21",status:"in",hour:"08:12"}];

data.forEach(({ date, status, hour }) => {
  if (date in result) {
    if (status == 'in' && hour < result[date].hourIn) result[date].hourIn = hour;
    else if (status == 'out' && hour > result[date].hourOut) result[date].hourOut = hour;
  } else result[date] = {
    date,
    hourIn: status == 'in' ? hour : '-',
    hourOut: status == 'out' ? hour : '-'
  };
});

result = Object.values(result);
console.log(result);

既然我已经这样做了,我不确定它会增加多少,但这里有一种使用 reduce 的方法:

const data = [
  {date:"19",status:"in",hour:"12:00"}, {date:"19",status:"in",hour:"12:20"}, {date:"19",status:"in",hour:"12:43"}, {date:"19",status:"out",hour:"16:16"},
  {date:"20",status:"in",hour:"07:30"}, {date:"20",status:"out",hour:"14:40"},
  {date:"21",status:"in",hour:"08:12"}
];

const new_hour = (field, status, current, new_val) =>
  field === status &&
    (
      current === '-' ||
      (status === 'in') === (new_val < current)
    ) ? new_val : current;

const hours_reducer = (acc, { date, status, hour }) =>
  Object.assign(acc, {
    [date]: {
      date,
      hourIn: new_hour('in', status, acc[date]?.hourIn || '-', hour),
      hourOut: new_hour('out', status, acc[date]?.hourOut || '-', hour),
    }
  });

const values = Object.values( data.reduce(hours_reducer, {}) );

console.log(values);