1

I want to merge item and purchases array of json into one by matching their property value.

Here's the source :

{
    "item": [
        {
            "invoiceId": 1
        },
        {
            "invoiceId": 2
        },
        {
            "invoiceId": 3
        }
    ],
    "purchase": [
        {
            "id": "1",
            "date": "12/1/2014"
        },
        {
            "id": "2",
            "date": "12/1/2014"
        },
        {
            "id": "3",
            "date": "12/1/2014"
        }
    ]
}

I want to produce something like this :

{
    "combined": [
        {
            "invoiceId": 1,
            "id": "1",
            "date": "12/1/2014"
        },
        {
            "invoiceId": 2,
            "id": "2",
            "date": "12/1/2014"
        },
        {
            "invoiceId": 3,
            "id": "3",
            "date": "12/1/2014"
        }
    ]
}

How can I match the item.invoiceId with purchase.id?

3 Answers 3

2

Solution

assuming obj is your object

var new_obj = {combined:[]};
obj["purchase"].forEach(function(a) {
    obj["item"].forEach(function(b){ 
        if (+b["invoiceId"]===(+a["id"])) {
            a["invoiceId"] = b["invoiceId"] || 0;//WILL MAKE INVOICEID 0 IF IT IS NOT DEFINE. CHANGE 0 TO YOUR NEEDS
            new_obj.combined.push(a);
        }
    });
});

How it works

The first .forEach() loops through obj.purchase. Then we loop through obj.item To check if their is a matching invoiceId (if you don't need to make sure their is a matching invoiceId, use the alternate code). Then, we simply add a new value to the new_obj


The result (copied from console) is:

{
    "combined":[
        {
            "id":"1",
            "date":"12/1/2014",
            "invoiceId":1
        },
        {
            "id":"2",
            "date":"12/1/2014",
            "invoiceId":2
        },
        {
            "id":"3",
            "date":"12/1/2014",
            "invoiceId":3
        }
    ]
} 

Alternative Code

Use this if you don't need to make sure, invoiceId is there

var new_obj = {combined:[]};

obj["purchase"].forEach(function(a){a["invoiceId"]=a["id"];new_obj.combined.push(a);});
Sign up to request clarification or add additional context in comments.

7 Comments

curious to know what is +a["a"] here
@JamesLemon That just converts it into an Number. It's shorthand for parseInt/parseFloat
@JamesLemon Simple fix, add a + before the b, I updated my answer. Here's your fiddle: jsfiddle.net/blue1086/ap417mde/1
just curious how the casting work. is it just add a + in any variable and it will become an integer?
@JamesLemon I'm guessing it thinks it's a math equation so it'll convert it. Also because multiplying *1 will convert it. Example '5'*1
|
0

One way of achieving what you want will be

var result = {};

var getMatchingPurchase = function(invoiceId) {
    return data.purchase.filter(function(purchase) {
        return invoiceId == purchase.id; 
    })[0];
};

result.combined = data.item.map(function(invoice) {
    var purchase = getMatchingPurchase(invoice.invoiceId);
    return {
        invoiceId: invoice.invoiceId,
        id: purchase.id,
        date: purchase.date
    };
});

console.log(result);

It will print like bellow

{ combined:
   [ { invoiceId: 1, id: '1', date: '12/1/2014' },
     { invoiceId: 2, id: '2', date: '12/1/2014' },
     { invoiceId: 3, id: '3', date: '12/1/2014' } ] }

Note:- I'm using map and filter functions which are not supported in IE8. If you want to use in IE8 you have to use for loop.

2 Comments

says invoice id is my priority, will the id become null and the loop is still going?
@JamesLemon do you mean if there is not matching purchase for an inovoice ?
0

If you have to support old browsers like IE8 (poor guy...), note that the native forEach might not be supported, in this case you can use lodash for cross-browser compatibility:

function getCombinedResult(source){
    var combinedList = [];
    _.each(source.item, function(item){
        _.each(source.purchase, function(purchase){
            if (item['invoiceId'].toString() != purchase['id'].toString()) return;
            var combinedItem = _.extend(item, purchase)
            combinedList.push(combinedItem);
        });
    })
    return {"combined": combinedList};
}

2 Comments

.forEach is a 1.9 specification. Pretty much every browser nowadays should support it, even IE
you're right, it's fine since IE 9, editted to make it more clear

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.