1

I'm trying to figure out the best way to organize this data in Javascript, so I apologize if this question is broader than usual.

I have data:

State, Zip
"CA", "945"
"CA", "934"
"MA", "934"
"MA", "021"
"MA", "021"
 etc.

I am trying to create some sort of Javascript Array that I can reference to get all the Zip in a certain State

This reference might look like:

State: "CA", Zip:["945", "934"]
State: "MA", Zip:["934", "021", "021"]

Does that make sense? Does something similar work with javascript?

I want to do it this way because on rare occasion a 3-digit Zip would exist in two States (as in the example above).


I was playing with the below code, but it does not work.

var stateArray = [],
var zipMapper = [];

for (var i = 0; i < data.length; i++){
    if (_.contains(stateArray,data[i].state) == false) {
        stateArray.push(data[i].state)
        zipMapper.push({state: data[i].state, zips: []})
        zipMapper[data[i].state].zips.push(data[zip])
    } else {
        zipMapper[data[i].state].zips.push(data[zip])
    }
}
7
  • How does data actually look? The pseudo representation is a bit hard to to tell. Commented Mar 17, 2016 at 18:49
  • what is the structure of your data? Is it an array? an object? Commented Mar 17, 2016 at 18:49
  • Please provide the data as JSON Commented Mar 17, 2016 at 18:51
  • What do you do with the grouped data? Commented Mar 17, 2016 at 18:57
  • @RajaprabhuAravindasamy the data is read in as a csv. So I believe it is an array of objects, with each object having one state and one zip Commented Mar 17, 2016 at 19:24

4 Answers 4

2

I suggest to change the data structure to version with fast access to the state and their Zips.

{
    "CA": [
        "945",
        "934"
    ],
    "MA": [
        "934",
        "021",
        "021"
    ]
}

To get zips from CA, just take grouped.CA or grouped['CA'].

The solution, you suggested, need always an interation until the data for a state is found. It makes access slow.

var data = [{ State: "CA", Zip: "945" }, { State: "CA", Zip: "934" }, { State: "MA", Zip: "934" }, { State: "MA", Zip: "021" }, { State: "MA", Zip: "021" }],
    grouped = function (array) {
        var r = {};
        array.forEach(function (a) {
            r[a.State] = r[a.State] || [];
            r[a.State].push(a.Zip);
        });
        return r;
    }(data);


document.write('<pre>' + JSON.stringify(grouped, 0, 4) + '</pre>');

Sign up to request clarification or add additional context in comments.

9 Comments

ah yes that is exactly how I want the data to look. I still need to run through your code (i'm a js newbie), but thanks for the idea and clarification, nina!
Ok despite that this is only four lines of code, I'm a little confused on r[a.State] = r[a.State] || [];. My understanding that this returns the state value unless it evaluates to false, in which case it returns an empty array []. However, there is a state value in every object so why is this needed / what does this actually do?
for the record, this worked exactly how I was looking, I just want to learn what is happening. thanks!
if r[a.State] is truty, an object/array, the the object is returned, not tru or false. if the value is falsey, then an empty array is returned.
ohhhhhh it makes sense now. Thanks for walking me through that (and for the initial code)!
|
0

I've created code with sample data. This might be helpful:

  var data = [{
    state: "CA",
    zip: "945"
  },
  {
    state: "CA",
    zip: "934"
  },
  {
    state: "MA",
    zip: "934"
  },
  {
    state: "MA",
    zip: "021"
  },
  {
    state: "MA",
    zip: "021"
  }
];
var zip_mapper = {};

for (var i = 0; i < data.length; i++) {
  if (!zip_mapper[data[i].state]) zip_mapper[data[i].state] = []; //zip codes array
  zip_mapper[data[i].state].push(data[i].zip);
}

// testing
for (var key in zip_mapper) {
  alert(key + "--->" + zip_mapper[key]);
}

Comments

0

Try this:

   var data = [{
      state: 'CA',
      zip: '945'
    },
    {
      state: 'CA',
      zip: '934'
    },
    {
      state: 'MA',
      zip: '934'
    },
    {
      state: 'MA',
      zip: '021'
    },
    {
      state: 'MA',
      zip: '021'
    },
  ];

  function exists(stateName, data) {
    var existIndex = -1;
    for (var i = 0; i < data.length; i++) {
      if (data[i].state === stateName) {
        existIndex = i;
        break;
      }
    }
    return existIndex;
  }
  var finalData = [],
    index;

  for (var i = 0; i < data.length; i++) {
    index = exists(data[i].state, finalData);
    if (index === -1) {
      finalData.push({
        state: data[i].state,
        zip: []
      })
      finalData[finalData.length - 1].zip.push(data[i].zip)
    } else {
      finalData[index].zip.push(data[i].zip)
    }
  }

  console.log(finalData);

Comments

0

Here is a way how to do it without a loop, relying on reduce only:

Explanation: Check if element exists in array, if not, then add it to the new acc array, if yes, find the index of that element and add the zip number to the zip array.

Solution

var data = [{
    state: 'CA',
    zip: '945'
  },
  {
    state: 'CA',
    zip: '934'
  },
  {
    state: 'MA',
    zip: '020'
  },
  {
    state: 'MA',
    zip: '021'
  },
  {
    state: 'MA',
    zip: '022'
  },
];

const groupedData = data.reduce((acc, x) => {
  const index = acc.findIndex(y => y.state === x.state);
  if (index < 0) {
    acc.push({
      state: x.state,
      zip: [x.zip]
    });
    return acc;
  }
  acc[index] = {
    ...acc[index],
    state: x.state,
    zip: [...acc[index].zip, x.zip]
  }
  return acc;
}, [])

console.log(groupedData)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.