Объединять и комбинировать элементы массива с одинаковой датой - PullRequest
2 голосов
/ 24 января 2020

У меня есть этот массив объектов:

var data = [
  {
    "x": "2020-01-24T10:30:02.000Z",
    "y": 2
  },
  {
    "x": "2020-01-24T08:19:07.000Z",
    "y": 2
  },
  {
    "x": "2020-01-23T16:12:36.000Z",
    "y": 5
  },
  {
    "x": "2020-01-23T08:19:07.000Z",
    "y": 2
  }
]

Я использую диаграмму Js для отображения данных в линейном графике, я не знаю, почему он не делает это сам , но я хочу объединить значения, которые имеют только те же year+month+date без часов, вывод должен быть:

var data = [
  {
    "x": "2020-01-24T00:00:00.000Z",
    "y": 4
  },
  {
    "x": "2020-01-23T00:00:00.000Z",
    "y": 7
  }
]

код, который у меня так:

const groupByDate = array => array.reduce((results, item) => {
  const current = results.find(i => new Date(i.x).getDate() === new Date(item.x).getDate());
  if (current) {
    for (let property in item) {
      if (property !== 'x') {
        current[property] = item[property];
      }
    }
  } else {
    results.push({...item});
  }
  return results;
}, []);

console.log(groupByDate(data));

Но Функция пока не суммирует y значения

Ответы [ 6 ]

2 голосов
/ 24 января 2020

Вы можете переместить find в l oop и взять только первые десять символов даты ISO 8601 для comapring.

var data = [{ x: "2020-01-24T10:30:02.000Z", y: 2 }, { x: "2020-01-24T08:19:07.000Z", y: 2 }, { x: "2020-01-23T16:12:36.000Z", y: 5 }, { x: "2020-01-23T08:19:07.000Z", y: 2 }],
    result = [];
   
for (let { x, y } of data) {                             // iterate data, get x and y
    x = x.slice(0, 10);                                  // take yyyy-mm-dd only
    let temp = result.find(q => q.x.slice(0, 10) === x); // look for same data
    if (temp) temp.y += y;                               // if found add to y
    else result.push({ x: x + 'T00:00:00.000Z', y });    // if not create object and push
}

console.log(result);

Более быстрый подход к объекту.

var data = [{ x: "2020-01-24T10:30:02.000Z", y: 2 }, { x: "2020-01-24T08:19:07.000Z", y: 2 }, { x: "2020-01-23T16:12:36.000Z", y: 5 }, { x: "2020-01-23T08:19:07.000Z", y: 2 }],
    hash = Object.create(null),
    result;
   
for (let { x, y } of data) {
    x = x.slice(0, 10);
    if (hash[x]) hash[x] += y;
    else hash[x] = y;
}

result = Object
    .entries(hash)
    .map(([x, y]) => ({ x: x + 'T00:00:00.000Z', y }));

console.log(result);
1 голос
/ 24 января 2020

Я использую Map для отображения даты на объект (быстрее, чем при использовании find).

const data = [
  { "x": "2020-01-24T10:30:02.000Z", "y": 2 },
  { "x": "2020-01-24T08:19:07.000Z", "y": 2 },
  { "x": "2020-01-23T16:12:36.000Z", "y": 5 },
  { "x": "2020-01-23T08:19:07.000Z", "y": 2 }
]

function groupData(data) {
  const map = new Map();                                // create a map
  for (const {x,y} of data) {                           // iterate over data
    const date = x.slice(0,10);                         // Assume that data is ISO 8601
    const mapData = map.get(date);                      // Get object for date
    if (mapData) {                                      // Do it exist?
      mapData.y += y;                                   // Yes, add y.
    } else {
      map.set(date, { x:`${date}T00:00:00.000Z`, y });  // No, set a new object.
    }
  }
  return Array.from(map.values());                      // Return as an array
}

const result = groupData(data);
console.log(result);
1 голос
/ 24 января 2020

Вы можете использовать .reduce() для создания объекта, где вы сохраняете каждую дату в качестве ключа в объекте, а суммарный объект - в качестве значения. Затем, чтобы получить эти суммарные объекты, вы можете использовать Object.values() на объекте, построенном .reduce():

const data = [ { "x": "2020-01-24T10:30:02.000Z", "y": 2 }, { "x": "2020-01-24T08:19:07.000Z", "y": 2 }, { "x": "2020-01-23T16:12:36.000Z", "y": 5 }, { "x": "2020-01-23T08:19:07.000Z", "y": 2 } ];

const res = Object.values(data.reduce((acc, obj) => {
  const key = obj.x.replace(/T.+/, ''); // get YYYY-MM-DD string
  acc[key] = acc[key] || {x: new Date(key).toISOString(),  y: 0}; // store date string as the key, ISO version of string part of the object.  
  acc[key].y += obj.y; // add to the total of the accumilated object
  return acc;
}, {}));

console.log(res);
0 голосов
/ 24 января 2020
let newData = []
data.map((item,index) => {
 var total =    data.reduce((acc,val) => {
    console.log(item.x.substring(0,10))
    if(item.x.substring(0,10) == val.x.substring(0,10)){
        console.log('matching case')
        return acc + val.y
    }
    else {
        return acc + 0
    }
  },0)
  console.log('t',total)
  if(newData.filter(i => i.x.substring(0,10) === item.x.substring(0,10)).length === 0)
    newData.push({"x":item.x,"y":total})
})
0 голосов
/ 24 января 2020
  • 1. Нормализовать дату данных на .map(...)
  • 2. Совокупные записи по дате .reduce(...)
  • 3. Преобразование объекта агрегации в массив объектов значений Object.values(...)
var data = [
  { "x": "2020-01-24T10:30:02.000Z", "y": 2},
  { "x": "2020-01-24T08:19:07.000Z", "y": 2},
  { "x": "2020-01-23T16:12:36.000Z", "y": 5},
  { "x": "2020-01-23T08:19:07.000Z", "y": 2}
]

Object.values(data.map(entry => {
  return {
    x: entry.x.replace(/T.*$/, 'T00:00:00.000Z'),
    y: entry.y
  }
}).reduce((accumulator, entry) => {
  const bucket = accumulator[entry.x] = accumulator[entry.x] || {
    x: entry.x,
    y: 0
  }
  bucket.y += entry.y
  return accumulator;
}, {}))
0 голосов
/ 24 января 2020

Я так и сделал.

var returnData = [];

for (var i =0; i<data.length;i+=1){
  var found = 0;
    for(var j =0; j<returnData.length;j++){
      if(data[i].x.slice(0, 10)===returnData[j].x.slice(0, 10)){
        returnData[j].y += data[i].y
        found = 1;
      }
    }
  if(found===0){
    returnData.push(data[i]);
  }
}

console.log(returnData)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...