qweeee
qweeee

Reputation: 63

Move array with days of week one day backwards js

I have such code

const weekDays = [
    { label: 'Mon', name: 'Monday' },
    { label: 'Tue', name: 'Tuesday' },
    { label: 'Wed', name: 'Wednesday' },
    { label: 'Thu', name: 'Thursday' },
    { label: 'Fri', name: 'Friday' },
    { label: 'Sat', name: 'Saturday' },
    { label: 'Sun', name: 'Sunday' },
];
 let daysOfWeek = ['Tue','Thu', 'Sun']

const firstDayIndex = weekDays.findIndex(day => day.label === daysOfWeek[0]) // get current day index
daysOfWeek.unshift(weekDays[(firstDayIndex || weekDays.length) - 1].label) // add previous day by index
daysOfWeek.pop() // remove last day
console.log(daysOfWeek)

Now daysOfWeek shows ["Mon", "Tue", "Thu"] but I wanted daysOfWeek to show ["Mon", "Wed", "Sat"] I mean, for each item of daysOfWeek to be one day backwards

Upvotes: 0

Views: 237

Answers (2)

pilchard
pilchard

Reputation: 12919

You could implement a circular doubly linked list, here indexed in an object by label.

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

const days_list = weekDays
  .map((day) => ({ day, prev: null, next: null }))
  .reduce((list, node, idx, arr) => {
    node.next = arr[(idx + 1) % arr.length];
    node.prev = arr[(idx + arr.length - 1) % arr.length];

    list[node.day.label] = node;

    return list;
  }, {});

const daysOfWeek = ['Tue', 'Thu', 'Sun'];

const prevDays = daysOfWeek.map((label) => days_list[label].prev.day.label);
console.log(...prevDays); // Mon Wed Sat

const nextDays = daysOfWeek.map((label) => days_list[label].next.day.label);
console.log(...nextDays); // Wed Fri Mon

// update daysOfWeek
daysOfWeek.forEach((label, i) => (daysOfWeek[i] = days_list[label].prev.day.label));

console.log('updated daysOfWeek: ', ...daysOfWeek);

As noted in the comments, using an extra two loops to make the list is not particularly efficient, even if the result is convenient to use. An alternative would be to declare utility functions to get the next/prev day given a label.

function next_day(label) {
  let index = weekDays.findIndex((day) => day.label === label);
  if (index === -1) throw `'${label}' is not a valid day label`;
  index = index === weekDays.length - 1 ? 0 : index;

  return weekDays[index + 1];
}

function prev_day(label) {
  let index = weekDays.findIndex((day) => day.label === label);
  if (index === -1) throw `'${label}' is not a valid day label`;
  index = index === 0 ? weekDays.length : index;

  return weekDays[index - 1];
}

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

function next_day(label) {
  let index = weekDays.findIndex((day) => day.label === label);
  if (index === -1) throw `'${label}' is not a valid day label`;
  index = index === weekDays.length - 1 ? 0 : index;

  return weekDays[index + 1];
}

function prev_day(label) {
  let index = weekDays.findIndex((day) => day.label === label);
  if (index === -1) throw `'${label}' is not a valid day label`;
  index = index === 0 ? weekDays.length : index;

  return weekDays[index - 1];
}

const daysOfWeek = ['Tue', 'Thu', 'Sun'];

const prevDays = daysOfWeek.map((day) => prev_day(day).label);
console.log('prevDays: ', ...prevDays); // Mon Wed Sat

const nextDays = daysOfWeek.map((day) => next_day(day).label);
console.log('nextDays: ', ...nextDays); // Wed Fri Mon

// or change daysOfWeek in place
daysOfWeek.forEach((day, i) => (daysOfWeek[i] = prev_day(day).label));
console.log('updated daysOfWeek: ', ...daysOfWeek);

These two functions share a lot of logic and can easily be combined into a single offset_day utility function which accepts an offset to return days +n or -n from the passed day label, if offset is omitted, 0, or evenly divisible by weekDays.length, it returns the day object of the passed label.

function offset_day(label, offset = 0) {
  let index = weekDays.findIndex((day) => day.label === label);

  if (index === -1) throw `'${label}' is not a valid day label`;

  const length = weekDays.length;
  const _offset = offset % length;
  if (_offset) {
    index = index + _offset;
    index = index < 0 ? index + length : index >= length ? index - length : index;
  }

  return weekDays[index];
}

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

function offset_day(label, offset = 0) {
  let index = weekDays.findIndex((day) => day.label === label);

  if (index === -1) throw `'${label}' is not a valid day label`;

  const length = weekDays.length;
  const _offset = offset % length;
  if (_offset) {
    index = index + _offset;
    index = index < 0 ? index + length : index >= length ? index - length : index;
  }

  return weekDays[index];
}

const daysOfWeek = ['Tue', 'Thu', 'Sun'];

const prevDays = daysOfWeek.map((day) => offset_day(day, -1).label);
console.log('prevDays: ', ...prevDays); // Mon Wed Sat

const nextDays = daysOfWeek.map((day) => offset_day(day, 1).label);
console.log('nextDays: ', ...nextDays); // Wed Fri Mon

// offset by 'n' days either way
const minusThree = daysOfWeek.map((day) => offset_day(day, -3).label);
console.log('minusThree: ', ...minusThree); // Sat Mon Thur

const plusThree = daysOfWeek.map((day) => offset_day(day, 3).label);
console.log('plusThree: ', ...plusThree); // Fri Sun Wed

Upvotes: 1

Nitheesh
Nitheesh

Reputation: 19986

Just loop through daysOfWeek and find its occurance index in weekDays. Update the node from daysOfWeek with the index reference from weekDays

Previous day Working Fiddle

const weekDays = [{ label: 'Mon', name: 'Monday' }, { label: 'Tue', name: 'Tuesday' }, { label: 'Wed', name: 'Wednesday' }, { label: 'Thu', name: 'Thursday' }, { label: 'Fri', name: 'Friday' },{ label: 'Sat', name: 'Saturday' },{ label: 'Sun', name: 'Sunday' }];
const daysOfWeek = ['Tue', 'Thu', 'Sun'];
// const daysOfWeek = ['Mon', 'Tue', 'Sun'];
daysOfWeek.forEach((day, dayIndex) => {
    let index = weekDays.findIndex(item => item.label === day);
    index = index === 0 ? weekDays.length : index;
    index !== -1 ? daysOfWeek[dayIndex] = weekDays[index - 1].label : null;
});
console.log(daysOfWeek);

Next day working logic

const weekDays = [{ label: 'Mon', name: 'Monday' },{ label: 'Tue', name: 'Tuesday' },{ label: 'Wed', name: 'Wednesday' },{ label: 'Thu', name: 'Thursday' },{ label: 'Fri', name: 'Friday' },{ label: 'Sat', name: 'Saturday' },{ label: 'Sun', name: 'Sunday' }];
let daysOfWeek = ['Tue', 'Thu', 'Sun'];
// let daysOfWeek = ['Mon', 'Tue', 'Sat'];
daysOfWeek.forEach((day, dayIndex) => {
    let index = weekDays.findIndex(item => item.label === day);
    // index = index === 0 ? weekDays.length : index;
    if (index !== -1) {
        index = index === weekDays.length - 1 ? -1 : index;
        daysOfWeek[dayIndex] = weekDays[index + 1].label;
    }
});
console.log(daysOfWeek);

Upvotes: 1

Related Questions