Transform arrays containing active days into a formatted string for easy readability

I have an array of boolean values that represent whether a store is open on each day of the week.

Here are some test cases:

Case 1:

Input data: [true, true, true, true, true, true, true]
Expected output: Open every day

Case 2:

Input data: [true, true, true, true, true, false, false]
Expected output: Monday to Friday

Case 3:

Input data: [true, true, false, false, true, true, true]
Expected output: Monday, Tuesday, Friday to Sunday

Case 4:

Input data: [true, false, false, true, false, false, true]
Expected output: Monday, Thursday, Sunday

Case 5:

Input data: [true, true, false, true, true, true, false]
Expected output: Monday, Tuesday, Thursday to Saturday

Case 6:

Input data: [true, false, false, false, false, false, false]
Expected output: Only open on Monday

I've created a solution here, but need help with cases 2-5

const daysLabels = [
  { label: "Monday", short: "Mon" },
  { label: "Tuesday", short: "Tue" },
  { label: "Wednesday", short: "Wed" },
  { label: "Thursday", short: "Thu" },
  { label: "Friday", short: "Fri" },
  { label: "Saturday", short: "Sat" },
  { label: "Sunday", short: "Sun" }
];

const getSchedule = ({ case: days }) => {
  let activeDays = [];
  for (let i = 0; i < [...days].length; i++) {
    const day = [...days][i];
    if (day) {
      activeDays.push({ ...daysLabels[i], value: day });
    }
  }

  if (activeDays.length === 7) {
    return "Open every day";
  }

  if (activeDays.length === 1) {
    return `Only open on ${activeDays[0].label}`;
  }

  return "#TODO";
};

Sandbox - link

Answer №1

Here is my response, although it is not an optimized version.

Include the following function:-

function calculateWeekDuration(events) {
  let index = 0;
  let weekDurationArray = [];

  for (let i = 0; i < events.length; i++) {
    const event = events[i];
    if (i === 0) {
      weekDurationArray[index] = [];
    }
    if (event) {
      weekDurationArray[index].push({ ...weekDaysLabels[i],
        value: event
      });
    } else {
      if (weekDurationArray[index].length > 0) {
        index += 1;
        weekDurationArray[index] = [];
      }
    }

  }

  // remove empty arrays
  weekDurationArray = weekDurationArray.filter(item => item.length > 0);

  // get only first and last event of each week duration
  weekDurationArray = weekDurationArray.map(weekDuration => {
    // combine inner array into string
    if (weekDuration.length > 1) {
      return `${weekDuration[0].short}-${weekDuration[weekDuration.length - 1].short}`;
    }
    return weekDuration[0].short;
  });

  return weekDurationArray.join(', ');

}

Also add the function's return statement within getSchedule

return calculateWeekDuration(eventList);

Answer №2

To create groups of day ranges with the correct labels, you can utilize the Array.reduce() method.

After that, a Array.map() call is used to retrieve only the label for each range.

All 6 test cases have been added and they are expected to pass successfully.

const daysLabels = [
  { label: "Monday", short: "Mon" },
  { label: "Tuesday", short: "Tue" },
  { label: "Wednesday", short: "Wed" },
  { label: "Thursday", short: "Thu" },
  { label: "Friday", short: "Fri" },
  { label: "Saturday", short: "Sat" },
  { label: "Sunday", short: "Sun" }
];

function getDayRange(input) {
    // Handling cases for all 7 days and single day...
    if (input.filter(active => active).length === 7) { 
        return 'Every day';
    } else if (input.filter(active => active).length === 1) { 
        return `Only ${daysLabels[input.findIndex(active => active)].label}`;
    }
    // For active days between 2 - 6
    return input.reduce((acc, active, idx) => {
        if (active) {
            if (!acc.length || acc[acc.length - 1].end < (idx - 1) ) { 
                acc.push({ start: idx, end: idx, label: daysLabels[idx].short, startLabel: daysLabels[idx].short });
            } else {
                acc[acc.length - 1].end = idx;
                acc[acc.length - 1].label = acc[acc.length - 1].startLabel + '-' + daysLabels[idx].short; 
            }
        }
        return acc;
    }, []).map(r => r.label).join(', ');
}

const cases = [
    { input: [true, true, true, true, true, true, true], expected: 'Every day' },
    { input: [true, true, true, true, true, false, false], expected: 'Mon-Fri' },
    { input: [true, true, false, false, true, true, true], expected: 'Mon-Tue, Fri-Sun' },
    { input: [true, false, false, true, false, false, true], expected: 'Mon, Thu, Sun' },
    { input: [true, true, false, true, true, true, false], expected: 'Mon-Tue, Thu-Sat' },
    { input: [true, false, false, false, false, false, false], expected: 'Only Monday' },
]
console.log(`Case`, '\t', 'Pass', '\t', 'Output')
cases.forEach(({ input, expected }, idx) => {
    let output = getDayRange(input);
    console.log(`${idx + 1}`, '\t', output === expected, '\t', output)
})
.as-console-wrapper { max-height: 100% !important; }

Answer №3

In this code snippet, I have defined a mapping array for the days of the week with corresponding indexes. You can make modifications to the text displayed based on whether the function returns results for only one day or every day.

// Mapping for days of the week
let indexMapping = [
    "Mon",
    "Tue",
    "Wed",
    "Thu",
    "Fri",
    "Sat",
    "Sun"
];

function getWeeks(arr){
    let list = [];
    let indexes = [];
    let item = [];

    // Retrieve all indexes where result is true
    arr.forEach((result,index) => {
        if(result) indexes.push(index);
    });

    // Populate the list with appropriate text based on sequential indexes
    indexes.map(i => {
        if(!indexes.includes(i-1)){
            if(item.length == 1){
                list.push(item[0]);
                item = [];
            }
            item.push(indexMapping[i]);
        }
        else if(!indexes.includes(i+1)){
            item.push(indexMapping[i]);
            list.push(item.join("-"));
            item = [];
        }
    });

    // Include single items in the list
    if(item.length == 1){
        list.push(item[0]);
    }
    return list;
}

// Test cases
let testArr2 = [true, true, true, true, true, false, false];
let testArr3 = [true, true, false, false, true, true, true];
let testArr4 = [true, false, false, true, false, false, true];
let testArr5 = [true, true, false, true, true, true, false];
getWeeks(testArr2); // Expected output: ['Mon-Fri']

Answer №4

Implementing Array#map along with regular expressions can significantly reduce the need for hard-coding, as shown below:

const daysLabels = [
  { label: "Monday", short: "Mon" },
  { label: "Tuesday", short: "Tue" },
  { label: "Wednesday", short: "Wed" },
  { label: "Thursday", short: "Thu" },
  { label: "Friday", short: "Fri" },
  { label: "Saturday", short: "Sat" },
  { label: "Sunday", short: "Sun" }
],

    getSchedule = ({ case: days }) => {
        const out = days.map((b,i) => b ? daysLabels[i].short : ":")
        .join(",").replace(/(?<![:\b]),[,A-za-z]*,(?![:\b])/g,"-")
        .replace(/(?<=[a-z]),(?=[A-Z])/g,"-")
        .replace(/[,\:]+/g,",").replace(/^[^A-Z]+|[^a-z]+$/g,"")
        .replace(/,/g,", ");
        return out === 'Mon-Sun' ? 'Every day' :
            !out.match(/[\-,]/) ? 
            `Only ${daysLabels.find(({short}) => short === out).label}` :
            out;
    };


const cases = [
    { input: [true, true, true, true, true, true, true], expected: 'Every day' },
    { input: [true, true, true, true, true, false, false], expected: 'Mon-Fri' },
    { input: [true, true, false, false, true, true, true], expected: 'Mon-Tue, Fri-Sun' },
    { input: [true, false, false, true, false, false, true], expected: 'Mon, Thu, Sun' },
    { input: [true, true, false, true, true, true, false], expected: 'Mon-Tue, Thu-Sat' },
    { input: [true, false, false, false, false, false, false], expected: 'Only Monday' },
    { input: [false, false, false, true, false, false, false], expected: 'Only Thursday' },
    { input: [false, false, false, false, false, false, true], expected: 'Only Sunday' }
]
console.log(`Case`, '\t', 'Pass', '\t', 'Output')
cases.forEach(({ input, expected }, idx) => {
    let output = getSchedule({case:input});
    console.log(`${idx + 1}`, '\t', output === expected, '\t', output)
});
.as-console-wrapper { max-height: 100% !important; }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

JQuery Master: Design your own circular slider

If you have ever come across JavaScript sliders, chances are they were in a linear format like this: However, I have a unique idea for a circular slider. Imagine a draggable button placed on the circle's circumference. This button can be moved along ...

Create a Java program that randomly generates an integer and keeps track of how many times it occurs

I'm currently working on a program that calculates how many times a user can flip a coin, with up to 1000 flips allowed. The program generates a random integer between 1 and 10 (even numbers represent heads, odd numbers represent tails) and stores all ...

Switch up the keyframe animation for a unique custom cursor style when hovering

I successfully developed a custom cursor using a div with jQuery. Is it possible to change the cursor style, such as applying animation keyframes, when hovering over the div? Below is the HTML code I used to create the custom cursor. <!DOCTYPE html> ...

GraphQL Query Fails to Save Result - Constantly Returns undefined

After running a query and logging the result, I encountered an issue where the result is always "undefined" when trying to work with it further (as shown in the second logging). It seems like I might be overlooking something obvious here. Any help would ...

When trying to return a string[,] type to main in C#, an implicit conversion error occurs, as it cannot be converted to a string type directly

Hey there! I'm a newcomer to game development and currently working on creating a console tictactoe game. My goal is to pass the board grid from the Board class to the main class in order to encapsulate the gameboard in its own class. I've set up ...

What strategies can I implement to create a memory-efficient grid class?

Creating a grid of objects in C++ typically involves defining a 2D array like this: class Grid { private: GridObject[5][5]; }; However, is there a more memory-efficient way to handle grids where not all tiles are occupied? For example, consider a che ...

Is there a way to direct an arrow towards an item in Aframe?

I'm trying to figure out how to point an arrow at a specific object in an Aframe scene. The arrow and object will be located at random positions, with the arrow initially facing "up" along the z-axis. I have some ideas on how to achieve this, but I&ap ...

Utilize Getcontext() on the members of the array that contain structures

typedef struct _ut_slot { ucontext_t uc; .... }*ut_slot; static ut_slot* table; //array of the structs void foo (int tab_size){ table = malloc ( tab_size *(sizeof (ut_slot))); // memory allocation for array of structs for(i = 0 ; i &l ...

I'm having trouble wrapping my head around this jQuery script

I'm in the process of designing a website that will feature two distinct themes: green and blue. By default, the color scheme is set to green, but users will have the option to switch to a blue theme by clicking on a button. After doing some research ...

Preventing Unwanted Scroll with jQuery

I'm currently working on a project where I have several description blocks that are meant to fade in when the corresponding image is clicked. The fading effect works fine, but there's an issue with the page scrolling up each time a new image is c ...

Title: "Customizing Labels on Stack Bars and Lines in D3.js Visualization"

Currently working on a stacked bar chart with a line chart on dual axis using D3.js and facing difficulty aligning labels correctly. Check out the code I have experimented with so far: https://plnkr.co/edit/doobXBC5hgzvGwDLvArF?p=preview I am looking to ...

What are the steps to organize a table's column of ants by date?

My goal is to organize the information in an antd table based on a Date column. I attempted to use the code snippet sorter: (a, b) => new Date(a) - new Date(b) for sorting purposes. Unfortunately, my attempts to address this issue can be found here bu ...

Positioning a material UI dialog in the middle of the screen, taking into account variations in its height

Dealing with an MUI Dialog that has a dynamic height can be frustrating, especially when it starts to "jump around" the screen as it adjusts to fit the content filtered by the user. Take a look at this issue: https://i.stack.imgur.com/IndlU.gif An easy f ...

Incorporate server-side tags into client-side HTML and JavaScript scripts without the use of template engines

My goal is to carry out the following operation within client-side JavaScript from a file served using Node and Express: var rootURL = <%= "someurlfromserverconfig" %>; I am solely hosting a web directory from my Node app without any template engin ...

Determine whether the click occurs inside or outside of a bar on a ChartJS graph

I'm currently working with a bar graph using chartJS. I'm trying to figure out how to detect where the user clicked - whether it was inside or outside of the bar region in chartJS. const waterFChart = new Chart(canvasRef.current, { plugins: [ ...

Update the page using ajax technology

Suppose there is an HTML element like this: <div id="dateRange">1d</div> This element is controlled by a JavaScript function: $("#30Days").click(function(){ $(".dateRange").html("30d"); }); $("#12Weeks").click(function(){ $(".dateR ...

Challenges with converting char arrays to strings in C++

#include <iostream> #include <string> #include <vector> using namespace std; int main () { string vet[10], aux; std::vector<char> name; int count=0, sum=0; while (count<10) { getline(cin, aux); ...

What is the best way to delete an item from a stream using the foreach method?

In my code, there are two arrays: arrA and arrB. These arrays contain Lists of objects of different types and the add function is used to convert objects from type A to type B. The goal is to transfer each object from arrA to arrB while also removing it fr ...

Showing associated table information in Vue.js

Currently, I am diving into the world of vuejs and harnessing the power of Laravel for the backend API. Within my project, I have set up tables named articles and articles_translations, where their relationships are defined in their respective models. For ...

Animating a group of images with JQuery

Hey there! I've been working on a simple animation for my webpage, but I'm having some trouble getting it to work the way I want. You can check out my page at . What I'm trying to achieve is having each image appear at its final position an ...