Ghazni
Ghazni

Reputation: 836

JavaScript - Array Slicing: based on a filter for different range

I have an array of objects as following:

Array:

[
  {
    "isChecked": false,
    "title": "00:00"
  },
  {
    "isChecked": false,
    "title": "00:30"
  },
  {
    "isChecked": false,
    "title": "01:00"
  },
  {
    "isChecked": false,
    "title": "01:30"
  },
  {
    "isChecked": false,
    "title": "02:00"
  },
  {
    "isChecked": false,
    "title": "02:30"
  },
  {
    "isChecked": false,
    "title": "03:00"
  },
  {
    "isChecked": false,
    "title": "03:30"
  },
  {
    "isChecked": false,
    "title": "04:00"
  },
  {
    "isChecked": false,
    "title": "04:30"
  },
  {
    "isChecked": false,
    "title": "05:00"
  },
  {
    "isChecked": false,
    "title": "05:30"
  },
  {
    "isChecked": false,
    "title": "06:00"
  },
  {
    "isChecked": false,
    "title": "06:30"
  },
  {
    "isChecked": false,
    "title": "07:00"
  },
  {
    "isChecked": false,
    "title": "07:30"
  },
  {
    "isChecked": false,
    "title": "08:00"
  },
  {
    "isChecked": false,
    "title": "08:30"
  },
  {
    "isChecked": false,
    "title": "09:00"
  },
  {
    "isChecked": false,
    "title": "09:30"
  },
  {
    "isChecked": false,
    "title": "10:00"
  },
  {
    "isChecked": false,
    "title": "10:30"
  },
  {
    "isChecked": false,
    "title": "11:00"
  },
  {
    "isChecked": false,
    "title": "11:30"
  }
]

UI: It is displaying like this:

enter image description here

User Action: When user select any time slots, like this: enter image description here

The Array will then have some checked times.

[
  {
    "isChecked": true,
    "title": "00:00"
  },
  {
    "isChecked": true,
    "title": "00:30"
  },
  {
    "isChecked": true,
    "title": "01:00"
  },
  {
    "isChecked": true,
    "title": "01:30"
  },
  {
    "isChecked": true,
    "title": "02:00"
  },
  {
    "isChecked": false,
    "title": "02:30"
  },
  {
    "isChecked": false,
    "title": "03:00"
  },
  {
    "isChecked": false,
    "title": "03:30"
  },
  {
    "isChecked": false,
    "title": "04:00"
  },
  {
    "isChecked": false,
    "title": "04:30"
  },
  {
    "isChecked": false,
    "title": "05:00"
  },
  {
    "isChecked": false,
    "title": "05:30"
  },
  {
    "isChecked": false,
    "title": "06:00"
  },
  {
    "isChecked": false,
    "title": "06:30"
  },
  {
    "isChecked": true,
    "title": "07:00"
  },
  {
    "isChecked": true,
    "title": "07:30"
  },
  {
    "isChecked": true,
    "title": "08:00"
  },
  {
    "isChecked": true,
    "title": "08:30"
  },
  {
    "isChecked": true,
    "title": "09:00"
  },
  {
    "isChecked": false,
    "title": "09:30"
  },
  {
    "isChecked": true,
    "title": "10:00"
  },
  {
    "isChecked": true,
    "title": "10:30"
  },
  {
    "isChecked": true,
    "title": "11:00"
  },
  {
    "isChecked": false,
    "title": "11:30"
  }
]

What I Want: A list of all time sessions ( start -to- end ), based on the selected time slots:

output:

[
  {
    "StartTime": "00:00",
    "EndTime": "02:00"
  },
{
    "StartTime": "07:00",
    "EndTime": "09:00"
  },
{
    "StartTime": "10:00",
    "EndTime": "11:00"
  },
]

I have tried it a little bit, but not getting the desired output.

here is the link of my code https://stackblitz.com/edit/ngoninit-wvnjfk

Your help will be highly appreciated !

Upvotes: 2

Views: 148

Answers (3)

Mr. Polywhirl
Mr. Polywhirl

Reputation: 48600

You can reduce the time slot dataset and return time blocks based on the current and previous time slots.

  1. Just check for isChecked and add a new block, if the previous slot was not checked.
  2. If the current one is not checked, but the previous one was, finish the time block.

const expected = getExpected(),
      actual   = calculateTimeBlocks(getInput());

console.log('Equal?:', JSON.stringify(actual) === JSON.stringify(expected));
console.log(actual);

function calculateTimeBlocks(timeSlots) {  
  return timeSlots.reduce((blocks, curr, index, arr) => {
    let prev = index > 0 ? arr[index - 1] : null;
    if (curr.isChecked) {
      if (!prev || !prev.isChecked) {
        blocks.push({ "StartTime" : curr.title });
      }
    } else {
      if (prev && prev.isChecked) {
        Object.assign(blocks[blocks.length - 1], {
          ["EndTime"] : prev.title
        });
      }
    }
    return blocks;
  }, []);
}

function getInput() {
  return [
    { "isChecked": true,  "title": "00:00" },
    { "isChecked": true,  "title": "00:30" },
    { "isChecked": true,  "title": "01:00" },
    { "isChecked": true,  "title": "01:30" },
    { "isChecked": true,  "title": "02:00" },
    { "isChecked": false, "title": "02:30" },
    { "isChecked": false, "title": "03:00" },
    { "isChecked": false, "title": "03:30" },
    { "isChecked": false, "title": "04:00" },
    { "isChecked": false, "title": "04:30" },
    { "isChecked": false, "title": "05:00" },
    { "isChecked": false, "title": "05:30" },
    { "isChecked": false, "title": "06:00" },
    { "isChecked": false, "title": "06:30" },
    { "isChecked": true,  "title": "07:00" },
    { "isChecked": true,  "title": "07:30" },
    { "isChecked": true,  "title": "08:00" },
    { "isChecked": true,  "title": "08:30" },
    { "isChecked": true,  "title": "09:00" },
    { "isChecked": false, "title": "09:30" },
    { "isChecked": true,  "title": "10:00" },
    { "isChecked": true,  "title": "10:30" },
    { "isChecked": true,  "title": "11:00" },
    { "isChecked": false, "title": "11:30" }
  ];
}

function getExpected() {
  return [
    { "StartTime": "00:00", "EndTime": "02:00" },
    { "StartTime": "07:00", "EndTime": "09:00" },
    { "StartTime": "10:00", "EndTime": "11:00" },
  ];
}
.as-console-wrapper { top: 0; max-height: 100% !important; }

Upvotes: 0

Vanojx1
Vanojx1

Reputation: 5574

Solution using js reduce. Chunk array then take first and last time.

const data=[{"isChecked":!0,"title":"00:00"},{"isChecked":!0,"title":"00:30"},{"isChecked":!0,"title":"01:00"},{"isChecked":!0,"title":"01:30"},{"isChecked":!0,"title":"02:00"},{"isChecked":!1,"title":"02:30"},{"isChecked":!1,"title":"03:00"},{"isChecked":!1,"title":"03:30"},{"isChecked":!1,"title":"04:00"},{"isChecked":!1,"title":"04:30"},{"isChecked":!1,"title":"05:00"},{"isChecked":!1,"title":"05:30"},{"isChecked":!1,"title":"06:00"},{"isChecked":!1,"title":"06:30"},{"isChecked":!0,"title":"07:00"},{"isChecked":!0,"title":"07:30"},{"isChecked":!0,"title":"08:00"},{"isChecked":!0,"title":"08:30"},{"isChecked":!0,"title":"09:00"},{"isChecked":!1,"title":"09:30"},{"isChecked":!0,"title":"10:00"},{"isChecked":!0,"title":"10:30"},{"isChecked":!0,"title":"11:00"},{"isChecked":!1,"title":"11:30"}];

const result = data.reduce(({ curr, times }, n) => {
    if (curr != n.isChecked && n.isChecked) times.push([]);
    if (n.isChecked) times[times.length-1].push(n.title);
    return { curr: n.isChecked, times };
}, { curr: false, times: [] }).times.map(range => ({ StartTime: range[0], EndTime: range[range.length-1] }));

console.log(result);

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386550

You could check the slot and predecessor and add a new object or update the last object.

var data = [{ isChecked: true, title: "00:00" }, { isChecked: true, title: "00:30" }, { isChecked: true, title: "01:00" }, { isChecked: true, title: "01:30" }, { isChecked: true, title: "02:00" }, { isChecked: false, title: "02:30" }, { isChecked: false, title: "03:00" }, { isChecked: false, title: "03:30" }, { isChecked: false, title: "04:00" }, { isChecked: false, title: "04:30" }, { isChecked: false, title: "05:00" }, { isChecked: false, title: "05:30" }, { isChecked: false, title: "06:00" }, { isChecked: false, title: "06:30" }, { isChecked: true, title: "07:00" }, { isChecked: true, title: "07:30" }, { isChecked: true, title: "08:00" }, { isChecked: true, title: "08:30" }, { isChecked: true, title: "09:00" }, { isChecked: false, title: "09:30" }, { isChecked: true, title: "10:00" }, { isChecked: true, title: "10:30" }, { isChecked: true, title: "11:00" }, { isChecked: false, title: "11:30" }],
    result = data.reduce((r, { isChecked, title }, i, a) => {
        if (!isChecked) return r;

        if (!i || !a[i - 1].isChecked) r.push({ StartTime: title, EndTime: title });
        else r[r.length - 1].EndTime = title;

        return r;
    }, []);         

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

Upvotes: 1

Related Questions