group by unique values of property - javascript

I got array of objects (tasks). Each task has property named 'category' and 'duration'.
var tasks = [
{
_id : "123",
category : "someCategory",
duration: "3432"
},
{
_id : "113",
category : "someCategory",
duration: "23"
},
{
_id : "124",
category : "someCategory 2",
duration: "1343"
},
{
_id : "2124",
category : "someCategory 2",
duration: "1343"
},
{
_id : "7124",
category : "someCategory 5",
duration: "53"
},
{
_id : "34",
category : "someCategory",
duration: "753"
}
]
I'd like to group tasks by category (unique) and sum duration of each category.
Result should be like:
var categories = ["someCategory", "someCategory 2" ... ]
var duration = [ <summary duration of "someCategory">, <summary duration of "someCategory 2">, ... ]
I have groupBy function which gives me all categories. I can find uniqueCategories using Array.prototype.filter but still I have to sum 'duration'.
var categoryMap = groupBy(tasks, 'category');
var uniqueCategories = categoryMap.get('category').filter((x, i, a) => a.indexOf(x) == i);
function groupBy(list, property) {
var map = new Map();
list.forEach(function(item) {
const key = property;
if(!map.has(key)) {
map.set(key, [item[key]])
} else {
map.get(key).push(item[key])
}
})
return map;
}
Then I create array of { key : value } and sum by key i.e.
[
{
someCategory : 3432
},
{
someCategory : 23
}
.
.
.
]
Finally I achieve my goal but code looks messy and isn't readable at all...
Is there better approach to do it in Javascript?

You could just return one object with category: duration.
var tasks = [{"_id":"123","category":"someCategory","duration":"3432"},{"_id":"113","category":"someCategory","duration":"23"},{"_id":"124","category":"someCategory 2","duration":"1343"},{"_id":"2124","category":"someCategory 2","duration":"1343"},{"_id":"7124","category":"someCategory 5","duration":"53"},{"_id":"34","category":"someCategory","duration":"753"}]
var result = tasks.reduce(function(r, e) {
r[e.category] = (r[e.category] || 0) + +e.duration
return r;
}, {})
console.log(result)

var tasks = [{"_id":"123","category":"someCategory","duration":"3432"},{"_id":"113","category":"someCategory","duration":"23"},{"_id":"124","category":"someCategory 2","duration":"1343"},{"_id":"2124","category":"someCategory 2","duration":"1343"},{"_id":"7124","category":"someCategory 5","duration":"53"},{"_id":"34","category":"someCategory","duration":"753"}]
var arr = [];
tasks.forEach(v => arr.push(v.category));
var newArr = [...new Set(arr)];
var arr2 = [];
newArr.forEach(function(v) {
var obj = {};
obj.category = v;
obj.duration = 0;
arr2.push(obj);
});
arr2.forEach(v => tasks.forEach(c => c.category == v.category ? v.duration += parseInt(c.duration) : v));
console.log(arr2);

Related

JavaScript - How to change object keys in an array of object?

I have an array of object :
let data = [
{ "date" : "17/03/2022", "count" : 2, "james#email.net" : 2 },
{
"date" : "17/05/2022",
"count" : 2,
"admin#email.com" : 1,
"secretary#email.uk" : 1
},
{ "date" : "17/07/2022", "count" : 7, "staff#email.us" : 7 },
];
I would like to remove "#" in the object key instead of the email address.
This is the expected output :
// Expected output:
data = [
{ "date" : "17/03/2022", "count" : 2, "james" : 2 },
{
"date" : "17/05/2022",
"count" : 2,
"admin" : 1,
"secretary" : 1
},
{ "date" : "17/07/2022", "count" : 7, "staff" : 7 },
];
Notes:
james is from james#email.net (1st element)
admin and secretary are from admin#email.com and secretary#email.uk, respectively (2nd element)
staff is from staff#email.us (3rd element)
and so on.
email as object keys are dynamic, meaning it can be "johndoe#email.co.uk", "mary#email.net", etc.
I have tried, but yet not successful :
for (let i = 0; i < data.length; i++) {
let keys = Object.keys(data[i]);
console.log(`key-${i+1} :`, keys); // [ 'date', 'count', 'admin#email.com', 'secretary#email.uk' ]
let emails = keys.filter(index => index.includes("#"));
console.log(`email-${i+1} :`, emails); // [ 'admin#email.com', 'secretary#email.uk' ]
let nameList = [];
for (let i = 0; i < emails.length; i++) {
let name = emails[i].split("#")[0];
nameList.push(name);
}
console.log(`name-${i+1} :`, nameList); // [ 'admin', 'secretary' ]
}
Thanks in advance.
You could create a function which splits the keys of the object keys at # and creates a new object using Object.fromEntries().
Here's a snippet:
const data = [{date:"17/03/2022",count:2,"james#email.net":2},{date:"17/05/2022",count:2,"admin#email.com":1,"secretary#email.uk":1},{date:"17/07/2022",count:7,"staff#email.us":7}];
const converter = o => Object.fromEntries(
Object.entries(o).map(([k, v]) => [k.split("#")[0], v])
)
console.log(
data.map(converter)
)
If Object.fromEntries() is not supported, you could use a simple loop through the array and then each object to create new objects like this:
const output = []
for (const o of data) {
const updated = {}
for (const key in o) {
updated[key.split("#")[0]] = o[key]
}
output.push(updated)
}
Try this as short as simple:
let data = [{
"date": "17/03/2022",
"count": 2,
"james#email.net": 2
},
{
"date": "17/05/2022",
"count": 2,
"admin#email.com": 1,
"secretary#email.uk": 1
},
{
"date": "17/07/2022",
"count": 7,
"staff#email.us": 7
},
];
const refinedData = JSON.parse(JSON.stringify(data));
refinedData.map((el, i) => {
Object.keys(el).map(e => {
if(e.includes('#')){
refinedData[i][e.slice(0, e.indexOf('#'))] = refinedData[i][e];
delete refinedData[i][e];
}
})
});
console.log(data, refinedData);
Try this improvement to prevent shallow copy and let me know your thoughts.
Can you try using this?
for (let i = 0; i < data.length; i++) {
let element = data[i];
let keys = Object.keys(element);
let emails = keys.filter(index => index.includes("#"));
for (let j = 0; j < emails.length; j++) {
let name = emails[j].split("#")[0];
let value = element[emails[j]];
Object.defineProperty(element, name, { value });
delete element[emails[j]];
}
}
console.log(data);

Convert an array to json object by javascript

I am stuck to solve this problem.
Convert an array below
var input = [
'animal/mammal/dog',
'animal/mammal/cat/tiger',
'animal/mammal/cat/lion',
'animal/mammal/elephant',
'animal/reptile',
'plant/sunflower'
]
to json Object
var expectedResult = {
"animal": {
"mammal": {
"dog": true,
"cat": {
"tiger": true,
"lion": true
},
"elephant": true
},
"reptile": true
},
"plant": {
"sunflower": true
}
}
Which data structure and algorithm can I apply for it?
Thanks
You need to first split each element to convert to array
using reverse reduce method you can convert them to object.
And your last step is merge this objects.
Lodash.js merge method is an one way to merge them.
var input = ['animal/mammal/dog','animal/mammal/cat/tiger','animal/mammal/cat/lion', 'animal/mammal/elephant','animal/reptile', 'plant/sunflower']
var finalbyLodash={}
input.forEach(x=>{
const keys = x.split("/");
const result = keys.reverse().reduce((res, key) => ({[key]: res}), true);
finalbyLodash = _.merge({}, finalbyLodash, result);
});
console.log(finalbyLodash);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script>
To make the process more understandable, break the problem down into pieces.
The first step is convert each string into something we can use, converting this:
"animal/mammal/dog"
into this:
[ "animal", "mammal", "dog" ]
That's an array of property names needed to build the final object.
Two functions will accomplish this for you, String.prototype.split() to split the string into an array, and Array.prototype.map() to transform each of the array elements:
let splitIntoNames = input.map(str => str.split('/'));
The intermediate result is this:
[
[ "animal", "mammal", "dog" ],
[ "animal", "mammal", "cat", "tiger" ],
[ "animal", "mammal", "cat", "lion" ],
[ "animal", "mammal", "elephant" ],
[ "animal", "reptile" ],
[ "plant", "sunflower" ]
]
Next step is to iterate over each array, using Array.prototype.forEach() to add properties to the object. You could add properties to the object with a for loop, but let's do that with a recursive function addName():
function addName(element, list, index) {
if (index >= list.length) {
return;
}
let name = list[index];
let isEndOfList = index === list.length - 1;
element[name] = element[name] || (isEndOfList ? true : {});
addName(element[name], list, index + 1);
}
let result = {};
splitIntoNames.forEach((list) => {
addName(result, list, 0);
});
The result:
result: {
"animal": {
"mammal": {
"dog": true,
"cat": {
"tiger": true,
"lion": true
},
"elephant": true
},
"reptile": true
},
"plant": {
"sunflower": true
}
}
const input = [
"animal/mammal/dog",
"animal/mammal/cat/tiger",
"animal/mammal/cat/lion",
"animal/mammal/elephant",
"animal/reptile",
"plant/sunflower",
];
let splitIntoNames = input.map((str) => str.split("/"));
console.log("splitIntoNames:", JSON.stringify(splitIntoNames, null, 2));
function addName(element, list, index) {
if (index >= list.length) {
return;
}
let name = list[index];
let isEndOfList = index === list.length - 1;
element[name] = element[name] || (isEndOfList ? true : {});
addName(element[name], list, index + 1);
}
let result = {};
splitIntoNames.forEach((list) => {
addName(result, list, 0);
});
console.log("result:", JSON.stringify(result, null, 2));
You can create a function that will slice every element from the array by "/" than you put the results into a variable and than just mount the Json. I mean something like that below:
window.onload = function() {
var expectedResult;
var input = [
'animal/mammal/dog',
'animal/mammal/cat/tiger',
'animal/mammal/cat/lion',
'animal/mammal/elephant',
'animal/reptile',
'plant/sunflower'
]
input.forEach(element => {
var data = element.split('/');
var dog = data[2] === 'dog' ? true : false
var tiger = data[2] === 'cat' && data[3] === 'tiger' ? true : false
var lion = data[2] === 'cat' && data[3] === 'lion' ? true : false
expectedResult = {
data[0]: {
data[1]: {
"dog": dog,
"cat": {
"tiger": tiger,
"lion": lion
}
}
}
}
})
}
Late to the party, here is my try. I'm implmenting recursive approach:
var input = ['animal/mammal/dog', 'animal/mammal/cat/tiger', 'animal/mammal/cat/lion', 'animal/mammal/elephant', 'animal/reptile', 'plant/sunflower'];
result = (buildObj = (array, Obj = {}) => {
array.forEach((val) => {
keys = val.split('/');
(nestedFn = (object) => {
outKey = keys.shift();
object[outKey] = object[outKey] || {};
if (keys.length == 0) object[outKey] = true;
if (keys.length > 0) nestedFn(object[outKey]);
})(Obj)
})
return Obj;
})(input);
console.log(result);
I try with array reduce, hope it help
let input = [
"animal/mammal/dog",
"animal/mammal/cat/tiger",
"animal/mammal/cat/lion",
"animal/elephant",
"animal/reptile",
"plant/sunflower",
];
let convertInput = (i = []) =>
i.reduce((prev, currItem = "") => {
let pointer = prev;
currItem.split("/").reduce((prevPre, currPre, preIdx, arrPre) => {
if (!pointer[currPre]) {
pointer[currPre] = preIdx === arrPre.length - 1 ? true : {};
}
pointer = pointer[currPre];
}, {});
return prev;
}, {});
console.log(JSON.stringify(convertInput(input), null, 4));

How to merge two objects based on id and group same key value pairs

var routePlan = [
{
"id" : 1,
"farmerName" : "Farmer1",
"farmerId" : 1
},
{
"id" : 2,
"farmerName" : "Farmer2",
"farmerId" : 2
},
{
"id" : 1,
"farmerName" : "Farmer3",
"farmerId" : 3
}
];
I want to merge objects having same id and create a new combined object using javascript or angularjs
var routePlan = [
{
"id" : 1,
"farmers" : [
{
"farmerName" : "Farmer1",
"farmerId" : 1
},
{
"farmerName" : "Farmer3",
"farmerId" : 3
}
]
},
{
"id" : 2,
"farmerName" : "Farmer3",
"farmerId" : 2
}
];
Please help me, I have seen lot of examples on the net but nothing seems to match my requirement
It can surely be improved, but this is a working solution:
let temp = routePlan.reduce(function(acc, item){
acc[item.id] = acc[item.id] || [];
acc[item.id].push({ "farmerName": item.farmerName, "farmerId" : item.farmerId });
return acc;
}, {});
let newRoute = Object.keys(temp).map(function(key){
let newObj = {}
if (temp[key].length > 1){
newObj.id = parseInt(key);
newObj.farmers = temp[key];
}
else
{
newObj = Object.assign({}, routePlan.find(elem => elem.id == key));
}
return newObj;
});
Note the reduce function used to group your objects by id.
You could take a hash table as reference to the groups.
var data = [{ id: 1, farmerName: "Farmer1", farmerId: 1 }, { id: 2, farmerName: "Farmer2", farmerId: 2 }, { id: 1, farmerName: "Farmer3", farmerId: 3 }],
hash = Object.create(null),
grouped = data.reduce(function (r, a) {
function getP(o) {
return ['farmerName', 'farmerId'].reduce(function (r, k) {
r[k] = o[k];
return r;
}, {});
}
if (!(a.id in hash)) {
hash[a.id] = r.push(a) - 1;
return r;
}
if (!r[hash[a.id]].farmers) {
r[hash[a.id]] = { id: a.id, farmers: [getP(r[hash[a.id]])] };
}
r[hash[a.id]].farmers.push(getP(a));
return r
}, []);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Javascript Fill array with missing object and value

I have an array like bellow each index contains different set of objects,I want to create an uniformal data where object missing in each index will with Value:0 ,
var d = [
[
{axis:"Email",value:59,id:1},
{axis:"Social Networks",value:56,id:2},
],
[
{axis:"Sending Money",value:18,id:6},
{axis:"Other",value:15,id:7},
]
];
how can I get an array like bellow using above above array
var d = [
[
{axis:"Email",value:59,id:1},
{axis:"Social Networks",value:56,id:2},
{axis:"Sending Money",value:0,id:6},
{axis:"Other",value:0,id:7},
],
[
{axis:"Email",value:0,id:1},
{axis:"Social Networks",value:0,id:2},
{axis:"Sending Money",value:18,id:6},
{axis:"Other",value:15,id:7},
]
];
There are two functions:
getAllEntries that find all objects and stores them into a variable accEntries. Then accEntries is used to search for all occurrences in a sub-array of d. This whole process is done in checkArray.
checkArray is used to fetch all found and not-found entries in d. Both Arrays (found and not-found) are then used to build a new sub-array that contains either found entries with certain values and/or not-found entries with values of 0.
Hope this helps:
var d = [
[
{
axis: 'Email',
value: 59,
id: 1
},
{
axis: 'Social Networks',
value: 56,
id: 2
},
],
[
{
axis: 'Sending Money',
value: 18,
id: 6
},
{
axis: 'Other',
value: 15,
id: 7
},
]
];
function getAllEntries(array) {
var uniqueEntries = [];
array.forEach(function (subarray) {
subarray.forEach(function (obj) {
if (uniqueEntries.indexOf(obj) === - 1) uniqueEntries.push(obj);
});
});
return uniqueEntries;
}
function checkArray(array, acceptedEntries) {
var result = [];
array.forEach(function (subArray) {
var subResult = [];
var foundEntries = [];
subArray.forEach(function (obj) {
if (foundEntries.indexOf(obj.axis) === - 1) foundEntries.push(obj.axis);
});
var notFound = acceptedEntries.filter(function (accepted) {
return foundEntries.indexOf(accepted.axis) === - 1;
});
foundEntries.forEach(function (found) {
subArray.forEach(function (obj) {
if (obj.axis === found) subResult.push(obj);
});
});
notFound.forEach(function (notfound, index) {
subResult.push({
axis: notfound.axis,
value: 0,
id: notfound.id
});
});
result.push(subResult);
});
return result;
}
var accEntries = getAllEntries(d);
var result = checkArray(d, accEntries);
console.log(result);
You can loop over the array to find all the unique objects and then again loop over to push the values that are not present comparing with the array of objects of unique keys.
You can use ES6 syntax to find if an object with an attribute is present like uniKeys.findIndex(obj => obj.axis === val.axis); and the to push with a zero value use the spread syntax like d[index].push({...val, value: 0});
Below is the snippet for the implementation
var d = [
[
{axis:"Email",value:59,id:1},
{axis:"Social Networks",value:56,id:2},
],
[
{axis:"Sending Money",value:18,id:6},
{axis:"Other",value:15,id:7},
{axis:"Social Networks",value:89,id:2},
]
];
var uniKeys = [];
$.each(d, function(index, item) {
$.each(item, function(idx, val){
const pos = uniKeys.findIndex(obj => obj.axis === val.axis);
if(pos == - 1) {
uniKeys.push(val);
}
})
})
$.each(d, function(index, item) {
var temp = [];
$.each(uniKeys, function(idx, val){
const pos = item.findIndex(obj => obj.axis === val.axis);
if(pos == - 1) {
d[index].push({...val, value: 0});
}
})
})
console.log(d);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
How about a short shallowCopy function (Object.assign is not available in IE) and otherwise less than 10 new lines of code?
var d = [
[
{axis:"Email",value:59,id:1},
{axis:"Social Networks",value:56,id:2}
],
[
{axis:"Sending Money",value:18,id:6},
{axis:"Other",value:15,id:7}
]
];
var newD_0 = [shallowCopy(d[0][0]), shallowCopy(d[0][1]), shallowCopy(d[1][0]), shallowCopy(d[1][1])];
var newD_1 = [shallowCopy(d[0][0]), shallowCopy(d[0][1]), shallowCopy(d[1][0]), shallowCopy(d[1][1])];
newD_0[2].id = 0;
newD_0[3].id = 0;
newD_1[0].id = 0;
newD_1[1].id = 0;
d = [newD_0, newD_1];
function shallowCopy(obj) {
var copy = {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = obj[key];
}
}
return copy;
}
console.log(JSON.stringify(d));
RESULT:
[
[
{
"axis":"Email",
"value":59,
"id":1
},
{
"axis":"Social Networks",
"value":56,
"id":2
},
{
"axis":"Sending Money",
"value":18,
"id":0
},
{
"axis":"Other",
"value":15,
"id":0
}
],
[
{
"axis":"Email",
"value":59,
"id":0
},
{
"axis":"Social Networks",
"value":56,
"id":0
},
{
"axis":"Sending Money",
"value":18,
"id":6
},
{
"axis":"Other",
"value":15,
"id":7
}
]
]

Summarize count of occurrences in an array of objects with Array#reduce

I want to summarize an array of objects and return the number of object occurrences in another array of objects. What is the best way to do this?
From this
var arrayOfSongs = [
{"title":"Blue","duration":161.71,"audioUrl":"/assets/music/blue","playing":false,"playedAt":"2016-12-21T22:58:55.203Z"},
{"title":"Blue","duration":161.71,"audioUrl":"/assets/music/blue","playing":false,"playedAt":"2016-12-21T22:58:55.203Z"},
{"title":"Blue","duration":161.71,"audioUrl":"/assets/music/blue","playing":false,"playedAt":"2016-12-21T22:58:55.203Z"},
{"title":"Green","duration":161.71,"audioUrl":"/assets/music/blue","playing":false,"playedAt":"2016-12-21T22:58:55.203Z"}
];
To this
var newArrayOfSongs = [
{"title": "Blue", "playCount": 3 },
{"title": "Green", "playCount": 1}
]
I have tried
arrayOfSongs.reduce(function(acc, cv) {
acc[cv.title] = (acc[cv.title] || 0) + 1;
return acc;
}, {});
}
But it returns an object:
{ "Blue": 3, "Green": 1};
You should pass the initial argument to the reduce function as an array instead of object and filter array for the existing value as below,
Working snippet:
var arrayOfSongs = [
{"title":"Blue","duration":161.71,"audioUrl":"/assets/music/blue","playing":false,"playedAt":"2016-12-21T22:58:55.203Z"},
{"title":"Blue","duration":161.71,"audioUrl":"/assets/music/blue","playing":false,"playedAt":"2016-12-21T22:58:55.203Z"},
{"title":"Blue","duration":161.71,"audioUrl":"/assets/music/blue","playing":false,"playedAt":"2016-12-21T22:58:55.203Z"},
{"title":"Green","duration":161.71,"audioUrl":"/assets/music/blue","playing":false,"playedAt":"2016-12-21T22:58:55.203Z"}
];
var newArrayOfSongs = arrayOfSongs.reduce(function(acc, cv) {
var arr = acc.filter(function(obj) {
return obj.title === cv.title;
});
if(arr.length === 0) {
acc.push({title: cv.title, playCount: 1});
} else {
arr[0].playCount += 1;
}
return acc;
}, []);
console.log(newArrayOfSongs);
To build on what you already have done, the next step is to "convert" the object to an array
var arrayOfSongs = [
{"title":"Blue","duration":161.71,"audioUrl":"/assets/music/blue","playing":false,"playedAt":"2016-12-21T22:58:55.203Z"},
{"title":"Blue","duration":161.71,"audioUrl":"/assets/music/blue","playing":false,"playedAt":"2016-12-21T22:58:55.203Z"},
{"title":"Blue","duration":161.71,"audioUrl":"/assets/music/blue","playing":false,"playedAt":"2016-12-21T22:58:55.203Z"},
{"title":"Green","duration":161.71,"audioUrl":"/assets/music/blue","playing":false,"playedAt":"2016-12-21T22:58:55.203Z"}
];
var obj = arrayOfSongs.reduce(function(acc, cv) {
acc[cv.title] = (acc[cv.title] || 0) + 1;
return acc;
}, {});
// *** added code starts here ***
var newArrayOfSongs = Object.keys(obj).map(function(title) {
return {
title: title,
playCount:obj[title]
};
});
console.log(newArrayOfSongs);
I recommend doing this in two stages. First, chunk the array by title, then map the chunks into the output you want. This will really help you in future changes. Doing this all in one pass is highly complex and will increase the chance of messing up in the future.
var arrayOfSongs = [
{"title":"Blue","duration":161.71,"audioUrl":"/assets/music/blue","playing":false,"playedAt":"2016-12-21T22:58:55.203Z"},
{"title":"Blue","duration":161.71,"audioUrl":"/assets/music/blue","playing":false,"playedAt":"2016-12-21T22:58:55.203Z"},
{"title":"Blue","duration":161.71,"audioUrl":"/assets/music/blue","playing":false,"playedAt":"2016-12-21T22:58:55.203Z"},
{"title":"Green","duration":161.71,"audioUrl":"/assets/music/blue","playing":false,"playedAt":"2016-12-21T22:58:55.203Z"}
];
function chunkByAttribute(arr, attr) {
return arr.reduce(function(acc, e) {
acc[e[attr]] = acc[e[attr]] || [];
acc[e[attr]].push(e);
return acc;
}, {});
}
var songsByTitle = chunkByAttribute(arrayOfSongs, 'title');
var formattedOutput = Object.keys(songsByTitle).map(function (title) {
return {
title: title,
playCount: songsByTitle[title].length
};
});
There, now everything is named according to what it does, everything does just one thing, and is a bit easier to follow.
https://jsfiddle.net/93e35wcq/
I used a set object to get the unique track titles, then used Array.map to splice those and return a song object that contains play count inside the track title.
The Data:
var arrayOfSongs = [{
"title": "Blue",
"duration": 161.71,
"audioUrl": "/assets/music/blue",
"playing": false,
"playedAt": "2016-12-21T22:58:55.203Z"
}, {
"title": "Blue",
"duration": 161.71,
"audioUrl": "/assets/music/blue",
"playing": false,
"playedAt": "2016-12-21T22:58:55.203Z"
}, {
"title": "Blue",
"duration": 161.71,
"audioUrl": "/assets/music/blue",
"playing": false,
"playedAt": "2016-12-21T22:58:55.203Z"
}, {
"title": "Green",
"duration": 161.71,
"audioUrl": "/assets/music/blue",
"playing": false,
"playedAt": "2016-12-21T22:58:55.203Z"
}];
The Function:
function getPlayCount(arrayOfSongs) {
let songObj = {};
let SongSet = new Set();
arrayOfSongs.map(obj => (SongSet.has(obj.title)) ? true : SongSet.add(obj.title));
for (let songTitle of SongSet.values()) {
songObj[songTitle] = {
playCount: 0
};
arrayOfSongs.map(obj => (obj.title === songTitle) ? songObj[songTitle].playCount++ : false)
}
return songObj;
}
console.log(getPlayCount(arrayOfSongs));
Which isn't exactly what you wanted formatting wise, but if you're married to it, this will do the trick:
function getPlayCount(arrayOfSongs) {
let songObj = {};
let SongSet = new Set();
arrayOfSongs.map(obj => (SongSet.has(obj.title)) ? true : SongSet.add(obj.title));
for (let songTitle of SongSet.values()) {
songObj[songTitle] = 0;
arrayOfSongs.map(obj => (obj.title === songTitle) ? songObj[songTitle]++ : false)
}
return songObj;
}
console.log(getPlayCount(arrayOfSongs));
https://jsfiddle.net/93e35wcq/1/

Categories

Resources