Уменьшить и сгруппировать по условию - PullRequest
0 голосов
/ 25 января 2020

У меня есть функция, которая рассчитывает максимальное количество событий, происходящих одновременно (ЧЧ: мм). В приведенном ниже примере три события происходят одновременно. Я хочу сгруппировать события, как в примере ниже.

Результат должен быть:

Цифровая встреча 00: 00-01.00

  • Группа 1:
    Поддержка 00.00-00.25

  • Группа 2:
    Книжная встреча 00: 30-01: 30
    Личная встреча 00:30 - 01: 30

Four events, where three occurs at the same time

Пока что я могу найти вхождения только для одного события. Я думаю, что я должен был бы использовать редуктор и условие?

let events = [
  {
    id: 9,
    start: 0,
    end: 60,
    title: "Digital meeting"
  },
  {
    id: 80,
    start: 30,
    end: 90,
    title: "Book meeting"
  },
  {
    id: 81,
    start: 30,
    end: 90,
    title: "Personal meeting"
  },
  {
    id: 84,
    start: 0,
    end: 24,
    title: "Support"
  }]

 events.forEach(item => {

// Find the matches
const matchedItems = events.filter(o => {
  return o.start <= item.end && o.end >= item.start && item.id !== o.id;
});

console.log(`Matched for ${item.id}`, matchedItems)

// Remove matches from the events array so there won't be duplicates
//remove(matchedItems);

// Format the items and place them in calendar grid
//format([item, ...matchedItems]);
   });

1 Ответ

0 голосов
/ 25 января 2020

Я реализовал функцию для вас, см. Код ниже, пожалуйста

// calculate if 2 events overlap, no matter of their provided order
function overlap(eventA, eventB) {

  // sort input
  const [first, second] = [eventA, eventB].sort((a, b) => a.start - b.start);
  
  // check if events overlap
  const overlap = first.end > second.start;
  return overlap;
}

// create a map object with the groups
// also sorted by time
// each group contains the event objects
function findOverlaps(events, query) {

  // result
  const groups = {};
  
  // event to build the groups for
  const queryEvent = events.find(e => e.title === query);
  
  // the other events to check of they overlap with the queried event
  const eventsWithoutQuery = events.filter(e => e.title !== query);
  eventsWithoutQuery.forEach(event => {
    const overlaps = overlap(event, queryEvent);
    
    // if there is an overlap
    if (overlaps) {
      // construct the groupname
      const groupName = `${event.start}-${event.end}`;

      // if the group alread exists use it, otherwise create an empty group (array)
      const group = groups[groupName] ? groups[groupName] : [];
      group.push(event);
      
      // put the group back to the groups map and name it accordingly
      groups[groupName] = group;
    }
  });
  
  // make sure the keys in the group are sorted (optional)
  const sortedKeys = Object.keys(groups).sort();
  const sortedGroups = sortedKeys.reduce(
    (acc, curr) => ({
      ...acc,
      [curr]: groups[curr]
    }),
    {}
  );
  
  // return sorted map
  return sortedGroups;
}


// the events
let events = [
    {
      id: 9,
      start: 0,
      end: 60,
      title: "Digital meeting"
    },
    {
      id: 80,
      start: 30,
      end: 90,
      title: "Book meeting"
    },
    {
      id: 81,
      start: 30,
      end: 90,
      title: "Personal meeting"
    },
    {
      id: 84,
      start: 0,
      end: 24,
      title: "Support"
    }
  ];
 

  console.log("Iterate over Digital meeting groups");
  // construct the groups for "Digial meeting" 
  const groups = findOverlaps(events, "Digital meeting");

  // iterate over overlap maps of Digital meeting
  for (const [groupName, eventsOfGroup] of Object.entries(groups)) {
  
    console.log(groupName, eventsOfGroup);
  }
  
  console.log("Iterate over everything");
  events.forEach(e => {   
    console.log("Groups for: " + e.title);
    for (const [groupName, eventsOfGroup] of Object.entries(findOverlaps(events, e.title))) {  
      console.log(groupName, eventsOfGroup);
    }  
  });
  
  
...