Как я могу объединить два массива объектов в JavaScript? - PullRequest
0 голосов
/ 16 сентября 2018

Каков наилучший способ объединения данных в JavaScript? Есть ли такие библиотеки, как, например, Pandas в Python или итерация - путь? У меня есть два массива с различными объектами внутри. Список orders содержит информацию о заказах в целом, а список ordersPayed содержит информацию о том, был ли заказ уже оплачен + сумма и т. Д.

const orders = [
{
    orderId: 1,
    orderDate: '2018-01-01',
    orderAmount: 100
},
{
    orderId: 2,
    orderDate: '2018-02-01',
    orderAmount: 100
},
{
    orderId: 3,
    orderDate: '2018-03-01',
    orderAmount: 100
},
{
    orderId: 4,
    orderDate: '2018-03-01',
    orderAmount: 100
}];
    
const ordersPayed = [
{
    orderId: 1,
    payedAmount: 90,
    debitorName: 'abc'
},
{
    orderId: 3,
    payedAmount: 80,
    debitorName: 'abc'
},
{
    orderId: 6,
    payedAmount: 90,
    debitorName: 'abc'
}];

let newOrderList = [];
    
for (i = 0; i < orders.length; i++) {
    for (j = 0; j < ordersPayed.length; j++) {
        if (orders[i].orderId == ordersPayed[j].orderId) {
            newOrderList.push(orders[i].orderId);
            newOrderList.push(orders[i].orderDate);
            newOrderList.push(orders[i].orderAmount);
            newOrderList.push(ordersPayed[j].payedAmount);
            newOrderList.push(ordersPayed[j].debitorName);
        }
        else if (j == (ordersPayed.length-1)) {
            newOrderList.push(orders[i].orderId);
            newOrderList.push(orders[i].orderDate);
            newOrderList.push(orders[i].orderAmount);
            newOrderList.push('not_payed_yet');
            newOrderList.push('not_known_yet');
        }
    }
}
    
console.log(newOrderList);

Совпадение производится клавишей orderId. В конце я хочу получить новый список со всеми заказами + соответствующую информацию о том, были ли они уже оплачены или нет.

Приведенный выше код - мой подход, но я не знаю, хорошо ли это по соображениям производительности и есть ли еще подводные камни. Поэтому я подумал о подходящей библиотеке или о чем-то подобном.

К сожалению, это не работает на 100% правильно. Результат должен выглядеть примерно так:

[{
    orderId: 1,
    orderDate: '2018-01-01',
    orderAmount: 100,
    payedAmount: 90
},
{
    orderId: 2,
    orderDate: '2018-02-01',
    orderAmount: 100,
    payedAmount: 'not_payed_yet'
},
{
    orderId: 3,
    orderDate: '2018-03-01',
    orderAmount: 100,
    payedAmount: 80
},
{
    orderId: 4,
    orderDate: '2018-03-01',
    orderAmount: 100,
    payedAmount: 'not_payed_yet'
}]

У кого-нибудь есть советы?

Ответы [ 5 ]

0 голосов
/ 17 сентября 2018

Используя lodash и обозначение стрелки ES6, решение может стать довольно коротким:

// Array of Javascript Objects 1:
const orders = [{
    orderId: 1,
    orderDate: '2018-01-01',
    orderAmount: 100
  },
  {
    orderId: 2,
    orderDate: '2018-02-01',
    orderAmount: 100
  },
  {
    orderId: 3,
    orderDate: '2018-03-01',
    orderAmount: 100
  },
  {
    orderId: 4,
    orderDate: '2018-03-01',
    orderAmount: 100
  }
];

// Array of Javascript Objects 2:
const ordersPayed = [{
    orderId: 1,
    payedAmount: 90,
    debitorName: 'abc'
  },
  {
    orderId: 3,
    payedAmount: 80,
    debitorName: 'abc'
  },
  {
    orderId: 6,
    payedAmount: 90,
    debitorName: 'abc'
  }
];


var merged = _.merge(_.keyBy(orders, 'orderId'), _.keyBy(ordersPayed, 'orderId'));

const newArr = _.map(merged, o => _.assign({
  "payedAmount": "not_payed_yet",
  "debitorName": "not_known_yet"
}, o));

var result = _.values(newArr);

console.log(result);
.as-console-wrapper {
  max-height: 100% !important;
  top: 0;
}
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>
0 голосов
/ 16 сентября 2018

В вашем коде есть небольшая ошибка. else if там не будет работать так, как вы хотите, потому что вы всегда будете помещать запись not found в новый массив всякий раз, когда не удается выполнить последнее совпадение. Вы можете попробовать эту скорректированную версию вашего кода:

const orders = [
{
    orderId: 1,
    orderDate: '2018-01-01',
    orderAmount: 100
},
{
    orderId: 2,
    orderDate: '2018-02-01',
    orderAmount: 100
},
{
    orderId: 3,
    orderDate: '2018-03-01',
    orderAmount: 100
},
{
    orderId: 4,
    orderDate: '2018-03-01',
    orderAmount: 100
}];
    
const ordersPayed = [
{
    orderId: 1,
    payedAmount: 90,
    debitorName: 'abc'
},
{
    orderId: 3,
    payedAmount: 80,
    debitorName: 'abc'
},
{
    orderId: 6,
    payedAmount: 90,
    debitorName: 'abc'
}];

let newOrderList = [];
    
for (i = 0; i < orders.length; i++) {
    let payed = false;
    for (j = 0; j < ordersPayed.length; j++) {
        if (orders[i].orderId == ordersPayed[j].orderId) {
            newOrderList.push({ orderId: orders[i].orderId,
                                orderDate: orders[i].orderDate,
                                orderAmount: orders[i].orderAmount,
                                payedAmount: ordersPayed[j].payedAmount,
                                debitorName: ordersPayed[j].debitorName });
            payed = true;
        }
    }
    if (!payed) {
        newOrderList.push({ orderId: orders[i].orderId,
                            orderDate: orders[i].orderDate,
                            orderAmount: orders[i].orderAmount,
                            payedAmount: 'not_payed_yet',
                            debitorName: 'not_known_yet' });
    }
}
    
console.log(newOrderList);

Но имейте в виду, что это сработает только в том случае, если у вас есть 1:1 связь между наборами данных. Это означает, что если вы можете иметь несколько записей в ordersPayed для записи в orders, результат также будет иметь несколько записей для этих заказов.

0 голосов
/ 16 сентября 2018
const newOrderList = orders.map((order, index) => {
   let payedOrder = ordersPayed.find(o => o.orderId === order.orderId);
   return Object.assign({}, order, payedOrder)
});
0 голосов
/ 16 сентября 2018

Для вашей проблемы я бы использовал Array.reduce с Array.find:

const newOrderList = orders.reduce((acc, order) => {
    const { orderId } = order;
    const orderPayed =  ordersPayed.find((orderPayed) => orderPayed.orderId === orderId);

    if (orderPayed) {
        return [
            ...acc,
            {
                ...order,
                ...orderPayed,
            }
        ];
    }

    return [
        ...acc,
        {
            ...order,
        },
    ];
}, []);
0 голосов
/ 16 сентября 2018

Вы можете попробовать следующее решение:

// Returns an array with order objects, which contain all information
let newOrderList = orders.map((order, index) => {
    let payedOrder = ordersPayed.find(o => o.orderId === order.orderId);

    // Returns a new object to not manipulate the original one
    return {
        orderId: order.orderId,
        orderDate: order.orderDate, 
        orderAmount: order.orderAmount, 
        payedAmount: payedOrder ? payedOrder.payedAmount : 'not_payed_yet', 
        debitorName: payedOrder ? payedOrder.debitorName: 'not_known_yet'
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...