0

I have two arrays of objects:

data = [
        {"value": 10.2, "cat": "A", "state": "MA"},
        {"value": 5.3, "cat": "B", "state": "MA"},
        {"value": 20.1, "cat": "A", "state": "NY"},
        {"value": 17.3, "cat": "B", "state": "NY"},
        {"value": 7.7, "cat": "A", "state": "CT"},
        {"value": 11.3, "cat": "B", "state": "CT"}
       ];

reference = [
             {"state": "MA", "increment": 4.1},
             {"state": "NY", "increment": 0.3},
             {"state": "CT", "increment": 20.6}
            ];

Questions

  1. How can I pull all state fields from reference without a loop? Specifically, a function like this reference.pullElement("state") returns something like ["MA", "NY", "CT"]. Does this exist? Do I have to create a reference object and build the following logic into a method?

    var states = []; for (var i = 0; i < reference.length; i++) { states.push(reference[i]["state"]); }

  2. How can I add the increment field from reference to value field in data, so that I can have a new array like this.

    output = [ {"value": 14.3, "cat": "A", "state": "MA"}, {"value": 9.4, "cat": "B", "state": "MA"}, {"value": 20.4, "cat": "A", "state": "NY"}, {"value": 17.6, "cat": "B", "state": "NY"}, {"value": 28.3, "cat": "A", "state": "CT"}, {"value": 31.9, "cat": "B", "state": "CT"} ];

I am trying to do the following for Question 2, but the actual data has a lot more categories than this. Is this the most efficient way to do it?

var output = data.slice();
for (var i = 0; i < data.length; i++) {
    for (var j = 0; j < reference.length; j++) {
        if (data[i]["state"] == reference[j]["state"]) {
            output[i]["value"] = data[i]["value"] + reference[j]["increment"];
        }
    }
}

Thanks!

Boxuan
  • 4,937
  • 6
  • 37
  • 73
  • 1
    Are you against using a library like underscore to do it, or do you need a solution from scratch? – Thierry Blais May 08 '14 at 19:03
  • Q1: [Array.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map). Note that internally, of course, you can't avoid looping through the collection. – Matt Burland May 08 '14 at 19:09
  • Q2: Transform `reference` into an object using `state` as the key and `increment` as it's value. Now you can look up increments using the state key and avoid nested loops. – Matt Burland May 08 '14 at 19:12

1 Answers1

2

If you are able to use the (relatively new) methods that are now available on arrays, you can do the following.

1.

// Produce an array of state strings
var states = reference.map(function(el) { return el.state; });

2.

// Produce an object with state strings as keys and increments as the values
var stateIncMap = reference.reduce(function(items, item) {
    items[item.state] = item.increment;
    return items;
}, {});

// Here's an alternate version of the above, using forEach() instead of reduce():
// var stateIncMap = {};
// reference.forEach(function(el) {
//     stateIncMap[el.state] = el.increment;
// });

// Update elements' values using the increments
data.forEach(function(el) {
    el.value += stateIncMap[el.state];
});

http://jsfiddle.net/vY5Sr/

JLRishe
  • 99,490
  • 19
  • 131
  • 169