What is the best way to join data in JavaScript? Are there libraries like e.g. Pandas
in Python
or is iteration the way to go? I have two arrays with different objects inside. The list orders
contains information about orders in general and the list ordersPayed
contains the information whether an order was already payed + the amount etc.
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);
What is the best way to join data in JavaScript? Are there libraries like e.g. Pandas
in Python
or is iteration the way to go? I have two arrays with different objects inside. The list orders
contains information about orders in general and the list ordersPayed
contains the information whether an order was already payed + the amount etc.
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);
The matching is done by the key orderId
. At the end I want to have a new list with all orders + the corresponding info whether they were already payed or not.
The code above is my approach to go, but I don't know if this is good for performance reasons and whether there are more pitfalls. So I thought of a matching library or something similar.
Unfortunately this doesn't work 100% correctly. The result should look something like this:
[{
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'
}]
Anybody got any tips?
Share Improve this question edited Nov 4, 2021 at 5:27 sunwarr10r asked Sep 16, 2018 at 12:28 sunwarr10rsunwarr10r 4,7979 gold badges64 silver badges119 bronze badges 3- Where is the data from? If it is from a database, you could solve this with a simple join on the server side. – Krisztián Balla Commented Sep 16, 2018 at 12:33
- asking for llibrary is ot. please add the wanted result as well, beside the problem you are facing. – Nina Scholz Commented Sep 16, 2018 at 12:33
- 2 Possible duplicate of Inner join two objects javascript – Hasan Fathi Commented Sep 16, 2018 at 13:01
5 Answers
Reset to default 6const newOrderList = orders.map((order, index) => {
let payedOrder = ordersPayed.find(o => o.orderId === order.orderId);
return Object.assign({}, order, payedOrder)
});
You can try following solution:
// 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'
}
});
Using lodash and ES6 arrow notation the solution can bee quite short:
// 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/npm/[email protected]/lodash.min.js"></script>
For your problem, I would use the Array.reduce
with 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,
},
];
}, []);
There is a small error in you code. The else if
there is not going to work the way you want, because you will always push a not found
entry to the new array, whenever the last match fails. You could try this adjusted version of your code:
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);
But keep in mind that this is only going to work if you have a 1:1
relationship between the datasets. Meaning if you can have multiple entries in ordersPayed
for an entry in orders
, the result is also going to have multiple entries for those orders.