Matthew Green
Matthew Green

Reputation: 10401

Combining similar objects together in JavaScript

I have some javascript that is fetching some JSON and I'm trying to combine certain rows of information together to use in a table.

The JSON looks like below:

[{"Code":"12345","Name":"foo","Service":"Payments"},
{"Code":"12345","Name":"foo","Service":"Marketing"},
{"Code":"23456","Name":"bar","Service":"Payments"},
{"Code":"23456","Name":"bar","Service":"Development"},
{"Code":"34567","Name":"baz","Service":"Marketing"}]

Basically some rows share the exact same information with each other except for one field, Service.

My thought was to try to turn each row into an object that I can either update or merge with another object that shares the same Code.

That object and code looks something like this:

function CustObj(code,name,hasPay,hasMarket,hasDev) {
  this.code = code;
  this.name = name;
  this.hasPay = hasPay;
  this.hasMarket = hasMarket;
  this.hasDev = hasDev;
}

function formatData(data) {
  var formatedData = [];
  for (var key in data) {
    var customer = new CustObj(data[key].Code,data[key].Name);
    switch (data[key].Service) {
      case 'Payments':
        customer.hasPay = true;
        break;
      case 'Marketing':
        customer.hasMarket = true;
        break;
      case 'Development':
        customer.hasDev = true;
        break;
    }
    formatedData.push(school);
  }
}

The problem is that I want to have one object for each unique Code but that has the correct amount of flags based on Service but I haven't figured out how to do that yet. I was looking at doing something like $.extend(formatedData,customer) to merge objects but I can't seem to get the right logic for locating the two objects that I'm trying to merge.

Any thoughts on how this can be accomplished?

Upvotes: 1

Views: 73

Answers (2)

jfriend00
jfriend00

Reputation: 707178

You can process the array for duplicates and create a new array where the "Service" property is an array of services that share the same Code and Name:

var data = [
    {"Code":"12345","Name":"foo","Service":"Payments"},
    {"Code":"12345","Name":"foo","Service":"Marketing"},
    {"Code":"23456","Name":"bar","Service":"Payments"},
    {"Code":"23456","Name":"bar","Service":"Development"},
    {"Code":"34567","Name":"baz","Service":"Marketing"}
];

function mergeServices(data) {
    var result = [], item, match, found;
    // for each array item
    for (var i = 0; i < data.length; i++) {
        item = data[i];
        found = false;
        for (var j = 0; j < result.length; j++) {
            // see if we have a dup of a previously existing item
            if (item.Code == result[j].Code && item.Name == result[j].Name) {
                // just add the Service name to the array of the previous item
                result[j].Service.push(item.Service);
                found = true;
                break;
            }
        }
        if (!found) {
            // copy the current row (so we can change it without changing original)
            var newItem = {};
            for (var prop in item) {
                newItem[prop] = item[prop];
            }
            // convert service to an array
            newItem.Service = [newItem.Service];
            result.push(newItem);
        }
    }
    return result;
}

var output = mergeServices(data);

That produces this output:

[
    {"Code":"12345","Name":"foo","Service":["Payments","Marketing"]},
    {"Code":"23456","Name":"bar","Service":["Payments","Development"]},
    {"Code":"34567","Name":"baz","Service":["Marketing"]}
]

Working jsFiddle: http://jsfiddle.net/jfriend00/6rU2z/

Upvotes: 2

abl
abl

Reputation: 5958

As you create your customers you can add them to a map (an object) so that they can be referenced by code. You only create customers that are not already in the map. For each row you get or create the corresponding customer and set the corresponding flag.

function formatData(data) {
    var customerMap = {};
    $(data).each(function(index, elem){

        // Get the customer if it is already in the map, else create it
        var customer = customerMap[elem.Code];
        if(!customer) {
            customer = new CustObj(elem.Code, elem.Name);
            customerMap[elem.Code] = customer;
        }

        // Add flags as appropiate
        switch (elem.Service) {
            case 'Payments':
                customer.hasPay = true;
                break;
            case 'Marketing':
                customer.hasMarket = true;
                break;
            case 'Development':
                customer.hasDev = true;
                break;
        }
    });

    // Convert map to array
    var formatedData = [];
    for(var code in customerMap){
        formatedData.push(customerMap[code]);
    }
}

function CustObj(code,name) {
    this.code = code;
    this.name = name;
    this.hasPay = false;
    this.hasMarket = false;
    this.hasDev = false;
}

EDIT I've created a fiddle to demonstrate this

JSFiddle

Upvotes: 2

Related Questions