使用函数式编程连接两个 JSON 对象数组,如 SQL 连接

Joining two arrays of JSON objects like an SQL join using functional programming

考虑一下,我有以下两个对象数组:

const existingAndArchivedBookings = 
[
 {"booking_id":-2},
 {"booking_id":-1},
 {"booking_id":999}
]

const newAndExistingBookings = 
[
 {bookingId:-2, name: "name1"}, 
 {bookingId:-3, name: "name1"}, 
 {bookingId:-1, name: "namex"}
]

我想做的是确定第二个数组中的哪些预订是新的,哪些是现有的。两个数组中的任何 bookingId 都存在。任何在第二个数组中但不在第一个数组中的 bookingID 都是新的。所以,求解的结果应该是一个数组,如下:

[ { bookingId: -2, existing: true, name: 'name1' },
  { bookingId: -3, existing: false, name: 'name1' },
  { bookingId: -1, existing: true, name: 'namex' } ]

我有一个解决方案(我将 post 作为答案),但我认为可能有更有效的方法。祝你好运。

这是我想出来的,好像有点啰嗦

const R = require('ramda')

const existingAndArchivedBookings = [{"booking_id":-2},{"booking_id":-1},{"booking_id":999}]
const newAndExistingBookings = [{bookingId:-2, name: "name1"}, {bookingId:-3, name: "name1"}, {bookingId:-1, name: "namex"}]

const existingAndArchivedKeys = existingAndArchivedBookings.map(value => value.booking_id)
const newAndExistingKeys = newAndExistingBookings.map(value => value.bookingId)

const existingKeys = existingAndArchivedKeys.filter(key => newAndExistingKeys.includes(key))
const newKeys = newAndExistingKeys.filter(key => !existingAndArchivedKeys.includes(key))

const existingBookingIds = existingKeys.map(key => {
    return {bookingId: key, existing: true}
})

const newBookingIds  = newKeys.map(key => {
    return {bookingId: key, existing: false}
})


const allArray = R.concat(newAndExistingBookings, R.concat(existingBookingIds, newBookingIds))

console.log(R.values(R.reduceBy(R.mergeLeft, {}, R.prop('bookingId'), allArray)))

您可以大大简化它,使用 Array.prototype.reduce 形成两个数组之间的比较结果,并使用 Array.prototype.findIndex 测试第二个数组中的对象是否存在于第一个数组中:

const existingAndArchivedBookings = 
[
 {"booking_id":-2},
 {"booking_id":-1},
 {"booking_id":999}
]

const newAndExistingBookings = 
[
 {bookingId:-2, name: "name1"}, 
 {bookingId:-3, name: "name1"}, 
 {bookingId:-1, name: "namex"}
]

  
const res = newAndExistingBookings.reduce((acc, ele) => {
  const idx = existingAndArchivedBookings.findIndex(b => b.booking_id === ele.bookingId);
  let existing = false;
  if(idx >=0 ){
    existing = true;
  }
  return acc.concat({bookingId : `${ele.bookingId}`, existing: `${existing}`, name: `${ele.name}`});
}, []);
console.log(res);

如果你想要一个非 R 答案:你可以使用一个简单的 map to iterate over the data, compare the booking ids in both arrays (with some) 和 return 一个新的对象数组。

const existingAndArchivedBookings = [{booking_id:-2},{booking_id:-1},{booking_id:999}];
const newAndExistingBookings = [{bookingId:-2, name: "name1"},{bookingId:-3, name: "name1"},{bookingId:-1, name: "namex"}];

function testBookings(arr1, arr2) {
  return arr2.map(({ bookingId, name }) => {
    const existing = arr1.some(obj => obj.booking_id === bookingId);
    return { bookingId, existing, name };
  });
}

const out = testBookings(existingAndArchivedBookings, newAndExistingBookings);

console.log(out);