合并在一系列物体中的重复和突变一些属性JavaScript

发布于 2025-02-05 04:56:22 字数 6057 浏览 4 评论 0原文

我有一个复杂的场景,在其中我需要在一系列对象中找到重复,并将它们合并以突变某些属性值。

数据来自一个对酒店保留的Excel文件,每个预订都有一个revervationNumber,当数组包含2个或更多的保留量,具有相同的proceservationnumber IT意味着它是相同的预订,但是有多个房间,所以我需要合并它们,但是第一个项目应保留为roomnumber(这是主房间),其余重复应汇总到extair_rooms(这是一个简单的数组,包含剩余的房间号,不包括主房间);另外,它需要汇总到具有以下结构的extramages属性:

extraRoomsAges: [
   {
     room: 34, // We get this from the roomNumber property
     // We get this from the mainRoomDistribution property
     adults: 0,
     infants: 0,
   },
],

因此,要更广泛地了解问题,这是我需要处理的数据的一个示例:

const data = [
  {
    reservationNumber: 'RX-0032466',
    fullName: 'John Doe',
    firstName: 'John',
    lastName: 'Doe',
    documentType: 'dni',
    hotel: 'hpp',
    documentID: null,
    extra_rooms: [],
    extraRoomsAges: [],
    mainRoomDistribution: {
      adults: 2,
      infants: 0,
    },
    totalCharges: 1754.28,
    agencyCode: 5,
    roomNumber: '63',
  },
  {
    reservationNumber: 'RX-0032466',
    fullName: 'John Doe',
    firstName: 'John',
    lastName: 'Doe',
    documentType: 'dni',
    hotel: 'hpp',
    documentID: null,
    extra_rooms: [],
    extraRoomsAges: [],
    mainRoomDistribution: {
      adults: 3,
      infants: 1,
    },
    totalCharges: 1954.49,
    agencyCode: 5,
    roomNumber: '64',
  },
  {
    reservationNumber: 'RX-0032466',
    fullName: 'John Doe',
    firstName: 'John',
    lastName: 'Doe',
    documentType: 'dni',
    hotel: 'hpp',
    documentID: null,
    extra_rooms: [],
    extraRoomsAges: [],
    mainRoomDistribution: {
      adults: 1,
      infants: 0,
    },
    totalCharges: 850.30,
    agencyCode: 5,
    roomNumber: '65',
  },
  {
    reservationNumber: 'RX-0032494',
    fullName: 'Jane Foster',
    firstName: 'Jane',
    lastName: 'Foster',
    documentType: 'dni',
    hotel: 'hpp',
    documentID: '123456789',
    extra_rooms: [],
    extraRoomsAges: [],
    mainRoomDistribution: {
      adults: 4,
      infants: 0,
    },
    totalCharges: 1540,
    agencyCode: 13,
    roomNumber: '40',
  },
]

结果应该像这样

  [
    {
      reservationNumber: 'RX-0032466',
      fullName: 'John Doe',
      firstName: 'John',
      lastName: 'Doe',
      documentType: 'dni',
      hotel: 'hpp',
      documentID: null,
      extra_rooms: [64, 65], // aggregates the remaining occurrences from the roomNumber property
      extraRoomsAges: [
        {
          room: 64,
          adults: 3,
          infants: 1
        },
        {
          room: 65,
          adults: 1,
          infants: 0,
        }
      ],
      mainRoomDistribution: {
        adults: 2,
        infants: 0,
      },
      totalCharges: 4559.07, //the sum of all the occurrences
      agencyCode: 5,
      roomNumber: '63', //remains as the main room from the first occurrence
    },
    {
      reservationNumber: 'RX-0032494',
      fullName: 'Jane Foster',
      firstName: 'Jane',
      lastName: 'Foster',
      documentType: 'dni',
      hotel: 'hpp',
      documentID: null,
      extra_rooms: [],
      extraRoomsAges: [],
      mainRoomDistribution: {
        adults: 4,
        infants: 0,
      },
      totalCharges: 1540,
      agencyCode: 13,
      roomNumber: '40',
    },
  ]

:我已经尝试使用此功能合并重复:

export function mergeObjectsInUnique<T>(array: T[], property: any): T[] {
  const newArray = new Map();
  array.forEach((item: T) => {
    const propertyValue = item[property];
    newArray.has(propertyValue)
      ? newArray.set(propertyValue, { ...item, ...newArray.get(propertyValue) })
      : newArray.set(propertyValue, item);
  });

  return Array.from(newArray.values());
}

console.log(mergeObjectsInUnique(data, 'reservationNumber'))

您可以看到这将正确合并了重复项,但是我只是找不到一种方法可以根据需要正确变异数据。

带有当前代码的摘要

const data = [{
    reservationNumber: 'RX-0032466',
    fullName: 'John Doe',
    firstName: 'John',
    lastName: 'Doe',
    documentType: 'dni',
    hotel: 'hpp',
    documentID: null,
    extra_rooms: [],
    extraRoomsAges: [],
    mainRoomDistribution: {
      adults: 2,
      infants: 0,
    },
    totalCharges: 1754.28,
    agencyCode: 5,
    roomNumber: '63',
  },
  {
    reservationNumber: 'RX-0032466',
    fullName: 'John Doe',
    firstName: 'John',
    lastName: 'Doe',
    documentType: 'dni',
    hotel: 'hpp',
    documentID: null,
    extra_rooms: [],
    extraRoomsAges: [],
    mainRoomDistribution: {
      adults: 3,
      infants: 1,
    },
    totalCharges: 1954.49,
    agencyCode: 5,
    roomNumber: '64',
  },
  {
    reservationNumber: 'RX-0032466',
    fullName: 'John Doe',
    firstName: 'John',
    lastName: 'Doe',
    documentType: 'dni',
    hotel: 'hpp',
    documentID: null,
    extra_rooms: [],
    extraRoomsAges: [],
    mainRoomDistribution: {
      adults: 1,
      infants: 0,
    },
    totalCharges: 850.30,
    agencyCode: 5,
    roomNumber: '65',
  },
  {
    reservationNumber: 'RX-0032494',
    fullName: 'Jane Foster',
    firstName: 'Jane',
    lastName: 'Foster',
    documentType: 'dni',
    hotel: 'hpp',
    documentID: '123456789',
    extra_rooms: [],
    extraRoomsAges: [],
    mainRoomDistribution: {
      adults: 4,
      infants: 0,
    },
    totalCharges: 1540,
    agencyCode: 13,
    roomNumber: '40',
  },
]

function mergeObjectsInUnique(array, property) {
  const newArray = new Map();
  array.forEach((item) => {
    const propertyValue = item[property];
    newArray.has(propertyValue) ?
      newArray.set(propertyValue, { ...item,
        ...newArray.get(propertyValue)
      }) :
      newArray.set(propertyValue, item);
  });

  return Array.from(newArray.values());
}

console.log(mergeObjectsInUnique(data, 'reservationNumber'))

玩的JSFIDDLE:

https://jsfiddle.net/

这是一个可以 如果可能的话,请解释答案。

提前致谢。

I have this complex scenario in which I need to find duplicates in an array of objects, and merge them mutating some property values.

The data comes from an excel file which has reservations for an hotel, each reservation has a reservationNumber which is unique, when the array contains 2 or more reservations with the same reservationNumber it means that it's the same reservation but with multiple rooms, so I need them to be merged, but the first item should remain as the roomNumber (which is the main room) and the rest of the duplicates should aggregate to extra_rooms (which is a simple array containing the remaining room numbers, excluding the main room); Also it needs to aggregate to extraRoomsAges property with the following structure:

extraRoomsAges: [
   {
     room: 34, // We get this from the roomNumber property
     // We get this from the mainRoomDistribution property
     adults: 0,
     infants: 0,
   },
],

So to get a wider view of the problem this is an example of the data I need to process:

const data = [
  {
    reservationNumber: 'RX-0032466',
    fullName: 'John Doe',
    firstName: 'John',
    lastName: 'Doe',
    documentType: 'dni',
    hotel: 'hpp',
    documentID: null,
    extra_rooms: [],
    extraRoomsAges: [],
    mainRoomDistribution: {
      adults: 2,
      infants: 0,
    },
    totalCharges: 1754.28,
    agencyCode: 5,
    roomNumber: '63',
  },
  {
    reservationNumber: 'RX-0032466',
    fullName: 'John Doe',
    firstName: 'John',
    lastName: 'Doe',
    documentType: 'dni',
    hotel: 'hpp',
    documentID: null,
    extra_rooms: [],
    extraRoomsAges: [],
    mainRoomDistribution: {
      adults: 3,
      infants: 1,
    },
    totalCharges: 1954.49,
    agencyCode: 5,
    roomNumber: '64',
  },
  {
    reservationNumber: 'RX-0032466',
    fullName: 'John Doe',
    firstName: 'John',
    lastName: 'Doe',
    documentType: 'dni',
    hotel: 'hpp',
    documentID: null,
    extra_rooms: [],
    extraRoomsAges: [],
    mainRoomDistribution: {
      adults: 1,
      infants: 0,
    },
    totalCharges: 850.30,
    agencyCode: 5,
    roomNumber: '65',
  },
  {
    reservationNumber: 'RX-0032494',
    fullName: 'Jane Foster',
    firstName: 'Jane',
    lastName: 'Foster',
    documentType: 'dni',
    hotel: 'hpp',
    documentID: '123456789',
    extra_rooms: [],
    extraRoomsAges: [],
    mainRoomDistribution: {
      adults: 4,
      infants: 0,
    },
    totalCharges: 1540,
    agencyCode: 13,
    roomNumber: '40',
  },
]

The result should look like this:

  [
    {
      reservationNumber: 'RX-0032466',
      fullName: 'John Doe',
      firstName: 'John',
      lastName: 'Doe',
      documentType: 'dni',
      hotel: 'hpp',
      documentID: null,
      extra_rooms: [64, 65], // aggregates the remaining occurrences from the roomNumber property
      extraRoomsAges: [
        {
          room: 64,
          adults: 3,
          infants: 1
        },
        {
          room: 65,
          adults: 1,
          infants: 0,
        }
      ],
      mainRoomDistribution: {
        adults: 2,
        infants: 0,
      },
      totalCharges: 4559.07, //the sum of all the occurrences
      agencyCode: 5,
      roomNumber: '63', //remains as the main room from the first occurrence
    },
    {
      reservationNumber: 'RX-0032494',
      fullName: 'Jane Foster',
      firstName: 'Jane',
      lastName: 'Foster',
      documentType: 'dni',
      hotel: 'hpp',
      documentID: null,
      extra_rooms: [],
      extraRoomsAges: [],
      mainRoomDistribution: {
        adults: 4,
        infants: 0,
      },
      totalCharges: 1540,
      agencyCode: 13,
      roomNumber: '40',
    },
  ]

So far I've tried with this function to merge duplicates:

export function mergeObjectsInUnique<T>(array: T[], property: any): T[] {
  const newArray = new Map();
  array.forEach((item: T) => {
    const propertyValue = item[property];
    newArray.has(propertyValue)
      ? newArray.set(propertyValue, { ...item, ...newArray.get(propertyValue) })
      : newArray.set(propertyValue, item);
  });

  return Array.from(newArray.values());
}

console.log(mergeObjectsInUnique(data, 'reservationNumber'))

As you can see this merges the duplicates correctly, but I just can't find a way to mutate the data properly as I need it.

Snippet with current code

const data = [{
    reservationNumber: 'RX-0032466',
    fullName: 'John Doe',
    firstName: 'John',
    lastName: 'Doe',
    documentType: 'dni',
    hotel: 'hpp',
    documentID: null,
    extra_rooms: [],
    extraRoomsAges: [],
    mainRoomDistribution: {
      adults: 2,
      infants: 0,
    },
    totalCharges: 1754.28,
    agencyCode: 5,
    roomNumber: '63',
  },
  {
    reservationNumber: 'RX-0032466',
    fullName: 'John Doe',
    firstName: 'John',
    lastName: 'Doe',
    documentType: 'dni',
    hotel: 'hpp',
    documentID: null,
    extra_rooms: [],
    extraRoomsAges: [],
    mainRoomDistribution: {
      adults: 3,
      infants: 1,
    },
    totalCharges: 1954.49,
    agencyCode: 5,
    roomNumber: '64',
  },
  {
    reservationNumber: 'RX-0032466',
    fullName: 'John Doe',
    firstName: 'John',
    lastName: 'Doe',
    documentType: 'dni',
    hotel: 'hpp',
    documentID: null,
    extra_rooms: [],
    extraRoomsAges: [],
    mainRoomDistribution: {
      adults: 1,
      infants: 0,
    },
    totalCharges: 850.30,
    agencyCode: 5,
    roomNumber: '65',
  },
  {
    reservationNumber: 'RX-0032494',
    fullName: 'Jane Foster',
    firstName: 'Jane',
    lastName: 'Foster',
    documentType: 'dni',
    hotel: 'hpp',
    documentID: '123456789',
    extra_rooms: [],
    extraRoomsAges: [],
    mainRoomDistribution: {
      adults: 4,
      infants: 0,
    },
    totalCharges: 1540,
    agencyCode: 13,
    roomNumber: '40',
  },
]

function mergeObjectsInUnique(array, property) {
  const newArray = new Map();
  array.forEach((item) => {
    const propertyValue = item[property];
    newArray.has(propertyValue) ?
      newArray.set(propertyValue, { ...item,
        ...newArray.get(propertyValue)
      }) :
      newArray.set(propertyValue, item);
  });

  return Array.from(newArray.values());
}

console.log(mergeObjectsInUnique(data, 'reservationNumber'))

Here is a JSFiddle to play around:

https://jsfiddle.net/ou036zwv/

I'd appreciate an explanation with the answer if possible.

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

羞稚 2025-02-12 04:56:24

我建议使用 array。降低() 在这里,使用reververationnumber对预订进行分组。

我们将为每个预订号码创建一个具有属性的对象,将每个预订分配给该属性。

如果预订已经存在预订编号,我们将通过将额外的房间号和额外的房间年龄附加到相关阵列来合并。我们还将将总费用添加到相关属性中。

合并到此对象后,我们将使用 object.values() 返回到数组。

这种方法非常有效,所花费的时间将是O(n),因为ACC [el.ReservationNumber]查找将非常快。

const data = [ { reservationNumber: 'RX-0032466', fullName: 'John Doe', firstName: 'John', lastName: 'Doe', documentType: 'dni', hotel: 'hpp', documentID: null, extra_rooms: [], extraRoomsAges: [], mainRoomDistribution: { adults: 2, infants: 0, }, totalCharges: 1754.28, agencyCode: 5, roomNumber: '63', }, { reservationNumber: 'RX-0032466', fullName: 'John Doe', firstName: 'John', lastName: 'Doe', documentType: 'dni', hotel: 'hpp', documentID: null, extra_rooms: [], extraRoomsAges: [], mainRoomDistribution: { adults: 3, infants: 1, }, totalCharges: 1954.49, agencyCode: 5, roomNumber: '64', }, { reservationNumber: 'RX-0032466', fullName: 'John Doe', firstName: 'John', lastName: 'Doe', documentType: 'dni', hotel: 'hpp', documentID: null, extra_rooms: [], extraRoomsAges: [], mainRoomDistribution: { adults: 1, infants: 0, }, totalCharges: 850.30, agencyCode: 5, roomNumber: '65', }, { reservationNumber: 'RX-0032494', fullName: 'Jane Foster', firstName: 'Jane', lastName: 'Foster', documentType: 'dni', hotel: 'hpp', documentID: '123456789', extra_rooms: [], extraRoomsAges: [], mainRoomDistribution: { adults: 4, infants: 0, }, totalCharges: 1540, agencyCode: 13, roomNumber: '40', }, ]

function mapRoomData(roomData) {
    return Object.values(roomData.reduce((acc, el) => { 
        if (acc[el.reservationNumber]) {
            // Merge data with existing reservation. 
            acc[el.reservationNumber].extra_rooms.push(+el.roomNumber);
            acc[el.reservationNumber].extraRoomsAges.push({ room: +el.roomNumber, ...el.mainRoomDistribution } );
            acc[el.reservationNumber].totalCharges += el.totalCharges;
        } else {
            // No reservation exists, create one...
            acc[el.reservationNumber] = el
        }
        return acc;
    }, {}))
}

const result = mapRoomData(data);
console.log('Result:', result);
.as-console-wrapper { max-height: 100% !important; }

I'd suggest using Array.reduce() here, grouping the reservations using the reservationNumber.

We'd create an object with properties for each reservation number, assigning each reservation to that property.

If a reservation already exists for the reservation number, we'll merge by appending the extra room numbers and extra room ages to the relevant arrays. We'd also add the totalCharges to the relevant property.

Once we've merged to this object, we'll use Object.values() to return to an array.

This approach is very efficient, the time taken will be of order O(N), since the acc[el.reservationNumber] lookups will be very fast.

const data = [ { reservationNumber: 'RX-0032466', fullName: 'John Doe', firstName: 'John', lastName: 'Doe', documentType: 'dni', hotel: 'hpp', documentID: null, extra_rooms: [], extraRoomsAges: [], mainRoomDistribution: { adults: 2, infants: 0, }, totalCharges: 1754.28, agencyCode: 5, roomNumber: '63', }, { reservationNumber: 'RX-0032466', fullName: 'John Doe', firstName: 'John', lastName: 'Doe', documentType: 'dni', hotel: 'hpp', documentID: null, extra_rooms: [], extraRoomsAges: [], mainRoomDistribution: { adults: 3, infants: 1, }, totalCharges: 1954.49, agencyCode: 5, roomNumber: '64', }, { reservationNumber: 'RX-0032466', fullName: 'John Doe', firstName: 'John', lastName: 'Doe', documentType: 'dni', hotel: 'hpp', documentID: null, extra_rooms: [], extraRoomsAges: [], mainRoomDistribution: { adults: 1, infants: 0, }, totalCharges: 850.30, agencyCode: 5, roomNumber: '65', }, { reservationNumber: 'RX-0032494', fullName: 'Jane Foster', firstName: 'Jane', lastName: 'Foster', documentType: 'dni', hotel: 'hpp', documentID: '123456789', extra_rooms: [], extraRoomsAges: [], mainRoomDistribution: { adults: 4, infants: 0, }, totalCharges: 1540, agencyCode: 13, roomNumber: '40', }, ]

function mapRoomData(roomData) {
    return Object.values(roomData.reduce((acc, el) => { 
        if (acc[el.reservationNumber]) {
            // Merge data with existing reservation. 
            acc[el.reservationNumber].extra_rooms.push(+el.roomNumber);
            acc[el.reservationNumber].extraRoomsAges.push({ room: +el.roomNumber, ...el.mainRoomDistribution } );
            acc[el.reservationNumber].totalCharges += el.totalCharges;
        } else {
            // No reservation exists, create one...
            acc[el.reservationNumber] = el
        }
        return acc;
    }, {}))
}

const result = mapRoomData(data);
console.log('Result:', result);
.as-console-wrapper { max-height: 100% !important; }

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文