假设我必须通过电子邮件发送我的列表中明天有约会的人,但是当我写电子邮件的主题时,我想知道谁明天有多个约会,所以我可以配置主题。此外,我不想一次发送多封电子邮件。我想发一封电子邮件说你有预约,或者你明天有多个预约。 (知道那些约会的身份也很棒。)
所以我有以下几点:
AllAppointments: [
{
id: 23,
name: "John",
email: "[email protected]",
appointment_date: tomorrow,
appointment_category: 3,
time: "morning"
}, {
id: 17,
name: "Alex",
email: "Alex @domain.com",
appointment_date: tomorrow,
appointment_category: 3,
time: "morning"
},
{
id: 22,
name: "Bob",
email: "[email protected]",
appointment_date: tomorrow,
appointment_category: 5,
time: "morning"
}, {
id: 35,
name: "John",
email: "[email protected]",
appointment_date: tomorrow,
appointment_category: 4,
time: "afternoon"
}
]
我想得到这些
MultipleAppointments : [
{
ids :[23,35],
name : John,
email : [email protected],
appointment_date : tomorrow,
appointment_categories: [ 3, 5 ]
}
]
singleAppointments : [
{
id: 17,
name : “Alex",
email : “[email protected]",
appointment_date : tomorrow,
appointment_category: 3,
time: “morning"
},
{
id: 22,
name : “Bob",
email : “[email protected]",
appointment_date : tomorrow,
appointment_categories: 5,
time: “morning"
}
]
我不打算在这里给出答案,而是告诉你如何解决它。它有助于将您想要执行的操作分解为更小的步骤,并将您想要执行的高级操作与您正在处理的具体数据类型分开考虑。
第一步是一个常见问题,许多实用程序库提供了groupBy
函数来完成它。 groupBy
将一个对象数组和一个函数从每个对象作为参数作为参数,并返回一个对象数组的数组。提供的函数返回相同值的对象将一起放在同一个数组中。对于您的情况,您可以这样调用groupBy
:
const groupedAppointments = groupBy(appointments, appointment => appointment.name);
尝试为自己实施groupBy
是一个很好的学习练习。作为提示,尝试使用for
循环或Array.reduce。
现在,我们有一个对象数组数组,如下所示:
[
[{
id: 23,
name: "John",
email: "[email protected]",
appointment_date: tomorrow,
appointment_category: 3,
time: "morning"
}, {
id: 35,
name: "John",
email: "[email protected]",
appointment_date: tomorrow,
appointment_category: 4,
time: "afternoon"
}],
[{
id: 17,
name: "Alex",
email: "Alex @domain.com",
appointment_date: tomorrow,
appointment_category: 3,
time: "morning"
}],
[{
id: 22,
name: "Bob",
email: "[email protected]",
appointment_date: tomorrow,
appointment_category: 5,
time: "morning"
}]
]
我们想要分离内部数组,并使一个变量保持所有单个约会,另一个变量保存所有多个约会。 JavaScript有一个内置的方法来处理像这样的数组filter。 Filter采用“tester”函数并将其应用于数组中的每个对象,并返回一个新数组,其中包含测试人员返回true
的所有值。因此,我们可以使用它来创建两个数组,一个包含只有一个项目的组,另一个包含其中包含多个项目的组:
const singleGroups = groupedAppointments.filter(group => group.length === 1);
const multipleGroups = groupedAppointments.filter(group => group.length > 1);
现在,singleGroups
仍然是一个约会数组的数组,每个内部数组只包含一个项目。它看起来像这样:
[
[{
id: 17,
name: "Alex",
email: "Alex @domain.com",
appointment_date: tomorrow,
appointment_category: 3,
time: "morning"
}],
[{
id: 22,
name: "Bob",
email: "[email protected]",
appointment_date: tomorrow,
appointment_category: 5,
time: "morning"
}]
]
我们想用它包含的一个项替换每个内部数组。如果要以相同的方式转换数组中的每个项目,可以使用内置的Array.map方法。这需要一个转换单个元素的函数,并将其应用于数组中的每个项目。所以要“取消组合”单个项目,我们会像这样使用它:
const singleAppointments = singleGroups.map(group => group[0]);
现在,singleAppointments
包含你想要的东西,一系列约会只发生一次:
[{
id: 17,
name: "Alex",
email: "Alex @domain.com",
appointment_date: tomorrow,
appointment_category: 3,
time: "morning"
}, {
id: 22,
name: "Bob",
email: "[email protected]",
appointment_date: tomorrow,
appointment_category: 5,
time: "morning"
}]
最后,我们需要将我们的multipleGroups
数组中的所有约会组转换为您在问题中的“MultipleAppointments”形状对象。这意味着我们有一个数组数组,我们需要一个对象数组,其中每个内部数组都被转换为一个对象,这是再次使用Array.map
的完美案例:
const multipleAppointments = multipleGroups.map(groupToMultipleAppointment);
function groupToMultipleAppointment(group) {
// ???
}
现在剩下的就是实现groupToMultipleAppointment
,它接受一系列约会,如下所示:
[{
id: 23,
name: "John",
email: "[email protected]",
appointment_date: tomorrow,
appointment_category: 3,
time: "morning"
}, {
id: 35,
name: "John",
email: "[email protected]",
appointment_date: tomorrow,
appointment_category: 4,
time: "afternoon"
}]
并返回如下对象:
{
ids:[23, 35],
name: John,
email: [email protected],
appointment_date: tomorrow,
appointment_categories: [3, 5]
}
我将把groupToMultipleAppointment
的实施留给你;我建议使用for
循环或Array.reduce
。
总而言之,这是我建议的代码,有些部分留给你自己填写:
const groupedAppointments = groupBy(appointments, appointment => appointment.name);
const singleGroups = groupedAppointments.filter(group => group.length === 1);
const multipleGroups = groupedAppointments.filter(group => group.length > 1);
const singleAppointments = singleGroups.map(group => group[0]);
const multipleAppointments = multipleGroups.map(groupToMultipleAppointment);
function groupToMultipleAppointment(group) {
// ???
// `group` is an array. Use `reduce` or a `for` loop to make a new object out of it.
}
function groupBy(array, getKeyForArray) {
// ???
// getKeyForArray is a function which takes an item from `array` and returns a string
// use a `for` loop or `reduce` to make a new array where
// objects with the same key are grouped together.
}
首先告诉您存储此数据的位置。 MongoDB的? MySQL的?记忆?
然后改变思维方式。您需要知道的是,您发送的电子邮件超过1个通知,而不是谁有多少次会议。而不是2个一维表,我建议你一个多维:
mails: {
'[email protected]': [
{
id: 23,
name: "John",
email: "[email protected]",
appointment_date: tomorrow,
appointment_category: 3,
time: "morning"
}, {
id: 35,
name: "John",
email: "[email protected]",
appointment_date: tomorrow,
appointment_category: 4,
time: "afternoon"
}
]
'[email protected]': [{
id: 17,
name: "Alex",
email: "[email protected]",
appointment_date: tomorrow,
appointment_category: 3,
time: "morning"
}
]
'[email protected]': [{
id: 22,
name: "Bob",
email: "[email protected]",
appointment_date: tomorrow,
appointment_category: 5,
time: "morning"
}]
}
这样的事情很容易创造。
let mails = {};
AllAppointments.forEach(one=> {
if(!mails[one.email])
mails[one.email] = [];
mails[one.email].push(one)
})
for(let email in mails)
sendMail(mails[email])