【问题标题】:Accessing nested dictionaries within a dictionary in Javascript在Javascript中访问字典中的嵌套字典
【发布时间】:2021-11-09 21:06:00
【问题描述】:

我希望创建一个日历,以根据我学校的当前日期检索假期。目前,我将数据结构化为字典,其中包含字典。

const holidays = {
  January: {
    "Martin Luther King Jr. Day": [17]
  },
  February: {},
  March: {
    "Spring Break": [16]
  },
  April: {},
  May: {},
  June: {},
  July: {
    "Fourth of July": [4]
  },
  August: {},
  September: {},
  October: {},
  November: {
    "Thanksgiving": [25, 26]
  },
  December: {
    "Christmas Eve": [23],
    "Christmas": [25],
    "Winter Break": [26, 27, 28, 29, 30, 31]
  }
};

我目前的方法是检查月份,然后检查日期的数组。如果日期存在于数组中,它将拉取键值以在上课时间网页上显示它是什么假期。我尝试了不同的方法来搜索子对象的数组,但都没有成功。

这是我的尝试:

function testCase() {
  for (var k in holidays) {
    if (x) {
      let y = holidays[x];
      for (var j in y) {
        if (date == y[j]) {
          return a.innerHTML = Object.keys(j[x]);
        } else {
          return a.innerHTML = "NO FIND";
        }
      }
    }
  }
}
```

【问题讨论】:

  • 使用includes()方法搜索嵌套数组。
  • 如果您对搜索功能的输入采用日期作为输入,那么我不确定这是要使用的最佳数据结构。我会通过拥有一组对象、开始和结束日期以及假期名称来简化这一点。然后,您可以比较给定的日期以查看它是否在该范围内,并且从该日期隐含月份。
  • 我一直在看它
  • 你不需要Object.keys(),因为j是关键。
  • 一旦发现不匹配的日期,您就会返回NO FIND。这并不意味着数组后面没有匹配的日期。

标签: javascript arrays dictionary


【解决方案1】:

从Date 对象中获取当前月份名称和日期。

您可以将月份名称用作holidays 对象的索引。然后你可以循环遍历该对象的键,使用includes() 来测试当前日期是否在该数组中,并返回假日名称。

如果你从不在循环内返回,你会在最后返回一个默认值。

const monthNames = ["January", "February", "March", "April", "May", "June",
  "July", "August", "September", "October", "November", "December"];

function testCase() {
  const today = new Date();
  const curMonth = monthNames[today.getMonth()];
  const curDate = today.getDate();
  let holidayMonth = holidays[curMonth];
  for (let holiday in holidayMonth) {
    if (holidays[holiday].includes(curDate)) {
      return holiday;
    }
  }
  return "No holiday found";
}

【讨论】:

  • 谢谢,我很难想象嵌套搜索,这很有帮助。
  • 我建议重命名 testCase 方法,因为它意味着任何东西。我认为像getCurrentHoliday 这样的东西会更好。
  • @KrystianSztadhaus 这只是我的填充名。当我修改、编辑和添加 cmets 时,我会返回并将原型中的函数重命名为对以后查找代码的人更有意义的名称。
【解决方案2】:

我会冒昧地说你的数据结构对于你可能需要的东西来说有点复杂,如果你能控制它,那么我建议你先简化成这样的东西:

const holidays = [
  {name: "Christmas", startFrom: new Date("2021-12-25T00:00:00Z"), endAt: new Date("2021-12-25T23:59:59Z")}
  ... // the other dates in your list
]

通过这样做,您就拥有了一个可以处理一系列日期的结构,其中月份包括在这些日期中。您现在只需要迭代一个维度,这应该会使您的代码更简单。

考虑到并非每年的所有假期都是固定的,这会有所帮助。例如,复活节并不总是在同一天(或同一个月),具有绝对时间范围,您可以在列表中为下一年定义相同的假期。

接下来,您可以定义一个接受日期输入的函数,并直接比较日期:


function FindHoliday(date) { // a Date Type input parameter
  return holidays.filter(({startFrom, endAt}) => startFrom <= date && endAt >= date)
} // returns all holidays that fit in this range.

数组过滤函数返回一个新数组,其中所有成员在给定的求值函数中求值为真,所以如果你得到一个空列表,则不存在假期

从这里开始,如果您只想写入 DOM...


a.innerHTML = FindHolidays(new Date("2021-12-25T12:00:00Z")).map(({name}) => name).join(", ")

【讨论】:

  • 好!我在这里尝试了其他一些建议,但是使用您建议的数据结构,我可以添加其他属性,以便合并时间表更改(例如,我可以让它检查一个地方半天以及完全关闭。)因为我的代码将JS 知识较少的同事可以看到,该结构足够直观,可以轻松进行更改。
  • 现在,我也在修改它周围的代码以使其干净。
  • 您可能需要考虑将数据导出到您导入的 .yaml 或 .json 文件中,您可以将日期存储为 UTC 字符串并在摄取时将其解析为日期。
  • 我也忘了提到一些假期重叠(取决于您的范围有多广) - 以上将愉快地返回同一天的多个假期
【解决方案3】:
UPDATE
I have added a datepicker to my solution below so you can switch the date and see how the function responds.

使用日期编号作为键和假期作为值来分解数据可能是一个更好的主意,这将特别有用,因为您可以检查当前日期编号的键值而不是而不是循环遍历每个 Object 键以查看哪个键(如果有)包含当前日期。

另外一个重要的注意事项是纯 JS 对象不尊重和保留插入顺序,因此最好使用对象数组,每月一个对象。使用对象数组不仅尊重插入顺序,而且使用零索引(意味着第一项的索引为 0),这也是 Date .getMonth() 方法的工作原理,如果该方法返回 0当前月份是一月,11 如果当前月份是十二月。这也让我们可以使用数组轻松定义多节假日。

考虑到这一点,我们仍然可以使用 JS cmets 来引用月份名称。在下面的示例中,我将日期输入的默认值设置为圣诞节2021-12-25,并包括当天的圣诞节和寒假,因此您可以看到该函数适用于多个假期。

const holidayStatus = document.getElementById('holiday-status'),
      dateInput = document.querySelector('input[type="date"]');

const holidays = [
  {   // January
     1: "New Years Day",
    17: "Martin Luther King Jr. Day"
  },
  {}, // February
  {   // March
    16: "Spring Break"
  },
  {}, // April
  {}, // May
  {}, // June
  {   // July
     4: "Fourth of July"
  },
  {}, // August
  {}, // September
  {}, // October
  {   // November
    25: "Thanksgiving",
    26: "Thanksgiving"
  },
  {   // December
    24: ["Christmas Eve", "Winter Break"],
    25: ["Christmas", "Winter Break"],
    26: "Winter Break",
    27: "Winter Break",
    28: "Winter Break",
    29: "Winter Break",
    30: "Winter Break",
    31: ["New Years Eve", "Winter Break"]
  },
];

const combineStrings = strs => (strs = [].concat(strs), strs.length === 1 ? strs[0] : (strs.length === 2 ? strs.join(' and ') : strs.map((str, i) => i === strs.length - 1 ? 'and ' + str : str).join(', ')));

const getDate = () => new Date(dateInput.value + ' 12:00');

const printHolidays = date => {
  const todaysHolidays = holidays[date.getMonth()][date.getDate()];
  holidayStatus.textContent = todaysHolidays ? (`This day's ${typeof todaysHolidays === 'string' || todaysHolidays.length === 1 ? 'holiday is' : 'holdays are'} ${combineStrings(todaysHolidays)}.`) : 'This day has no holidays.';
};
printHolidays(getDate());

dateInput.addEventListener('change', () => {
  printHolidays(getDate());
});
#holiday-status {
  display: inline-block;
  margin-top: 5px;
  padding: 5px 10px;
  border: 2px solid #f00;
  box-sizing: border-box;
}
&lt;div&gt;Using the date: &lt;input type="date" value="2021-12-25"&gt;&lt;/div&gt;&lt;span id="holiday-status"&gt;&lt;/span&gt;

我添加的辅助函数combineStrings如果存在数组则动态组合多个字符串,如果传递的是简单字符串则返回传递的字符串。

以下是一些不同字符串和字符串数组将返回的示例:

combineStrings("Holiday 1")
// -> "Holiday 1"
combineStrings(["Holiday 1", "Holiday 2"])
// -> "Holiday 1 and Holiday 2"
combineStrings(["Holiday 1", "Holiday 2", "Holiday 3"])
// -> "Holiday 1, Holiday 2, and Holiday 3"

【讨论】:

    猜你喜欢
    • 2012-07-26
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 2013-10-06
    • 2018-02-09
    • 2016-07-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多