Martin Jinda
Martin Jinda

Reputation: 488

Convert JS array to objects

I have a problem with the correct converting array to the form what I need from a graph plugin. I have a JSON which looks like below, from this file I have to count how many titles I have (see pic. 1). Hope you will understand from the pictures.

[
  {
    "name": "Mike Frost",
    "title": "value_1",
    "gender": "Male"
  },
  {
    "name": "Hans Karl",
    "title": "value_6",
    "gender": "Male"
  },
  {
    "name": "Kelly Clarkson",
    "title": "value_3",
    "gender": "Female"
  },
  ...
]

This what I've got so far:

enter image description here

This what I need:

enter image description here

There is my script which counts values from JSON.

var employeeData = require('json!../path/to/json.json');
var obj = [];
for (var i = 0, j = employeeData.length; i < j; i++) {
    if (obj[employeeData[i]['title']]) {
        obj[employeeData[i]['title']]++;
    }
    else {
        obj[employeeData[i]['title']] = 1;
    }
}

Upvotes: 0

Views: 109

Answers (3)

Nina Scholz
Nina Scholz

Reputation: 386530

You could iterate the array and count the occurence of the same titles.

var data = [{ "name": "Mike Frost", "title": "value_1", "gender": "Male" }, { "name": "Hans Karl", "title": "value_6", "gender": "Male" }, { "name": "Kelly Clarkson", "title": "value_3", "gender": "Female" }, { "name": "Kelly Clarkson", "title": "value_3", "gender": "Female" }, ],
    result = data.reduce(function (hash) {
        return function (r, a) {
            if (!hash[a.title]) {
                hash[a.title] = { label: a.title, value: 0 };
                r.push(hash[a.title]);
            }
            hash[a.title].value++;
            return r;
        };
    }(Object.create(null)), []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

ES6 with Map

var data = [{ "name": "Mike Frost", "title": "value_1", "gender": "Male" }, { "name": "Hans Karl", "title": "value_6", "gender": "Male" }, { "name": "Kelly Clarkson", "title": "value_3", "gender": "Female" }, { "name": "Kelly Clarkson", "title": "value_3", "gender": "Female" }, ],
    result = data.reduce(
        (map =>
            (r, a) =>
                (!map.has(a.title) && map.set(a.title, r[r.push({ label: a.title, value: 0 }) - 1]), map.get(a.title).value++, r)
        )(new Map), []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 0

kukkuz
kukkuz

Reputation: 42352

You can use Array.prototype.reduce and a hash table to group the data - see demo below:

var object=[{name:"Mike Frost",title:"value_1",gender:"Male"},{name:"Hans Karl",title:"value_6",gender:"Male"},{name:"Kelly Clarkson",title:"value_3",gender:"Female"},{name:"Mike Frost",title:"value_1",gender:"Male"},{name:"Hans Karl",title:"value_6",gender:"Male"}];

var result = object.reduce(function(hash){
   return function(prev, curr){
     if(hash[curr.title])
       hash[curr.title].value++;
     else {
       hash[curr.title] = {label: curr.title, value: 1};
       prev.push(hash[curr.title]);
     }
     return prev;
   };
}(Object.create(null)), []);

console.log(result);
.as-console-wrapper{top:0;max-height:100%!important;}

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074028

One convenient way to do this is with a map (either a real Map if you're using ES2015, or an object we're using as a map if you're using ES5 or earlier). You build a new array and also keep track of the array entries in the map keyed by the value_X value:

var json = '[' +
'  {' +
'    "name": "Mike Frost",' +
'    "title": "value_1",' +
'    "gender": "Male"' +
'  },' +
'  {' +
'    "name": "Hans Karl",' +
'    "title": "value_6",' +
'    "gender": "Male"' +
'  },' +
'  {' +
'    "name": "Another Six",' +
'    "title": "value_6",' +
'    "gender": "Male"' +
'  },' +
'  {' +
'    "name": "Kelly Clarkson",' +
'    "title": "value_3",' +
'    "gender": "Female"' +
'  },' +
'  {' +
'    "name": "Another 3",' +
'    "title": "value_3",' +
'    "gender": "Female"' +
'  },' +
'  {' +
'    "name": "Yet Another 3",' +
'    "title": "value_3",' +
'    "gender": "Female"' +
'  }' +
']';

// Parse the JSON
var data = JSON.parse(json);

// The new array we'll build
var newArray = [];

// Our "map"
var map = Object.create(null);

// Loop the parsed data
data.forEach(function(entry) {
    // Get the existing new entry if any
    var mapEntry = map[entry.title];
    if (mapEntry) {
        // We have one, increase its `value`
        ++mapEntry.value;
    } else {
        // There isn't one, create it with a count of 1
        // and save it to the array
        mapEntry = map[entry.title] = {
            label: entry.title,
            value: 1
        };
        newArray.push(mapEntry);
    }
});

// Done
console.log(newArray);

That can be written much more concisely, but I wanted to call out the individual parts of what I was doing.

In ES2015+:

const json = `[
  {
    "name": "Mike Frost",
    "title": "value_1",
    "gender": "Male"
  },
  {
    "name": "Hans Karl",
    "title": "value_6",
    "gender": "Male"
  },
  {
    "name": "Another Six",
    "title": "value_6",
    "gender": "Male"
  },
  {
    "name": "Kelly Clarkson",
    "title": "value_3",
    "gender": "Female"
  },
  {
    "name": "Another 3",
    "title": "value_3",
    "gender": "Female"
  },
  {
    "name": "Yet Another 3",
    "title": "value_3",
    "gender": "Female"
  }
]`;

// Parse the JSON
const data = JSON.parse(json);

// The new array we'll build
const newArray = [];

// Our map
const map = new Map();

// Loop the parsed data
data.forEach(entry => {
    // Get the existing new entry if any
    let mapEntry = map.get(entry.title);
    if (mapEntry) {
        // We have one, increase its `value`
        ++mapEntry.value;
    } else {
        // There isn't one, create it with a count of 1
        // and save it to the array
        mapEntry = {
            label: entry.title,
            value: 1
        };
        map.set(entry.title, mapEntry);
        newArray.push(mapEntry);
    }
});

// Done
console.log(newArray);

Upvotes: 1

Related Questions