从另一个数组中的多个对象创建对象数组

时间:2019-03-03 22:04:08

标签: javascript node.js

假设我必须给列表中明天有约会的人发送电子邮件, 但是,当我编写电子邮件主题时,我想知道谁明天有多个约会,因此可以配置主题。 另外,我也不想一次发送多封电子邮件。我想发送一封电子邮件,说您已经预约或明天要预约多个。 (知道这些约会的ID也很高兴。)

所以我有以下内容:

AllAppointments: [
    {
        id: 23,
        name: "John",
        email: "John@domain.com",
        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: "Bob@domain.com",
        appointment_date: tomorrow,
        appointment_category: 5,
        time: "morning"
    }, {
        id: 35,
        name: "John",
        email: "John@domain.com",
        appointment_date: tomorrow,
        appointment_category: 4,
        time: "afternoon"
    }

]

我想要这些

MultipleAppointments : [

        {
            ids :[23,35],
            name : John,
            email : John@domain.com,
            appointment_date : tomorrow,
            appointment_categories: [ 3, 5  ]
        }
]

singleAppointments : [ 

        { 
            id: 17,
            name : “Alex",
            email : “Alex@domain.com",
            appointment_date : tomorrow,
            appointment_category:  3,
            time: “morning"
        },


        { 
            id: 22,
            name : “Bob",
            email : “Bob@domain.com",
            appointment_date : tomorrow,
            appointment_categories:  5,
             time: “morning"
        }


]

2 个答案:

答案 0 :(得分:1)

我不仅会在这里给出答案,还将向您介绍如何解决。它有助于将您想做的事情分解为更小的步骤,并考虑您要与正在处理的具体数据类型分开进行的高级操作。

  • 首先,您希望根据它们共有的键将一些对象分组在一起
  • 第二,您想将仅包含1个对象的组与包含多个对象的组分开
  • 第三,您要将每个“多个约会”组中的所有对象组合到一个新对象中。

第一步是一个常见问题,许多实用程序库都提供了一个groupBy函数。 groupBy将对象数组和从每个对象到字符串的函数作为参数,然后返回对象数组的数组。提供的函数为其返回相同值的对象将一起放置在同一数组中。对于您的情况,您可以这样呼叫groupBy

const groupedAppointments = groupBy(appointments, appointment => appointment.name);

尝试自己实施groupBy是一个很好的学习练习。作为提示,请尝试使用for循环或Array.reduce

现在,我们有了对象数组,就像这样:

[
  [{
    id: 23,
    name: "John",
    email: "John@domain.com",
    appointment_date: tomorrow,
    appointment_category: 3,
    time: "morning"
  }, {
    id: 35,
    name: "John",
    email: "John@domain.com",
    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: "Bob@domain.com",
    appointment_date: tomorrow,
    appointment_category: 5,
    time: "morning"
  }]
]

我们要分离出内部数组,并使一个变量保存所有单个约会,而另一个变量保存所有多个约会。 JavaScript有一个内置方法,用于处理像这样的数组filter。筛选器采用“测试程序”功能,并将其应用于数组中的每个对象,然后返回一个新数组,其中包含测试程序针对其返回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: "Bob@domain.com",
    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: "Bob@domain.com",
  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: "John@domain.com",
  appointment_date: tomorrow,
  appointment_category: 3,
  time: "morning"
}, {
  id: 35,
  name: "John",
  email: "John@domain.com",
  appointment_date: tomorrow,
  appointment_category: 4,
  time: "afternoon"
}]

并返回这样的对象:

{
  ids:[23, 35],
  name: John,
  email: John@domain.com,
  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.
}

答案 1 :(得分:0)

首先告诉您该数据的存储位置。 Mongodb? MySQL的?记忆吗?

然后改变思维方式。您需要知道的是,您向哪一封电子邮件发送了多个通知,而不是谁召开了多少次会议。建议您不要使用2个一维表,而是一个多维表:

mails: {
 'John@domain.com': [
{
        id: 23,
        name: "John",
        email: "John@domain.com",
        appointment_date: tomorrow,
        appointment_category: 3,
        time: "morning"
    },  {
        id: 35,
        name: "John",
        email: "John@domain.com",
        appointment_date: tomorrow,
        appointment_category: 4,
        time: "afternoon"
    }
]
'Alex@domain.com': [{
        id: 17,
        name: "Alex",
        email: "Alex@domain.com",
        appointment_date: tomorrow,
        appointment_category: 3,
        time: "morning"
    }
]
'Bob@domain.com': [{
        id: 22,
        name: "Bob",
        email: "Bob@domain.com",
        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])