GroupBy using underscore.js using nested JSON object - javascript

I am trying to group this JSON by using BroadCategory attribute of category
[{
"brand": "Brand3",
"category": {
"popularity_index": 7,
"BroadCategory ": "BroadCategory4",
"MainCategory": "MainCategory410",
"GeneralCategory": "GeneralCategory41"
},
"description": "colonialism",
"discount": 17,
"id": 9
}, {
"brand": "Brand2",
"category": {
"popularity_index": 5,
"BroadCategory ": "BroadCategory2",
"MainCategory": "MainCategory210",
"GeneralCategory": "GeneralCategory21"
},
"description": "desc2",
"discount": 15,
"id": 2
}]
I went through underscore.js - _.groupBy nested attribute but this has array inside JSON for location
I tried something like:
var grpArray = _.groupBy(products, function (element) {
return element.category.BroadCategory;
})
but its not working. Why can't I access BroadCategory ?

You have to trim a space "BroadCategory "
"BroadCategory ": "BroadCategory2",
Change to:
"BroadCategory": "BroadCategory2",
OR:
_.groupBy(products, function (element) {
return element.category['BroadCategory '];
})

Related

Accessing nested array properties

This may be extremely simple but I've not been able to figure out how to iterate over and access the properties in the following mix (I think) of arrays and nested objects:
myFilters = {
"color_Filter": [{
"name": "BLUE",
"count": 1,
"dataId": "BLUE"
},
{
"name": "Black",
"count": 5,
"dataId": "Black"
},
{
"name": "Blue",
"count": 14,
"dataId": "Blue"
}
],
"size_Filter": [{
"name": "10",
"count": 16,
"dataId": "10"
},
{
"name": "12",
"count": 16,
"dataId": "12"
}
]
}
What would the correct looping structure be here to pull out name, count etc from the above? The desired output is to output a string from the above with color_Filter=BLUE,Black,Blue/size_Filter=10,12
I've tried a few different approaches and none of them have been successful so far.
You could map the entries of the object and create a string for each key. Get the name from the value array using map. Then join the array of strings with a /
const myFilters = {color_Filter:[{name:"BLUE",count:1,dataId:"BLUE"},{name:"Black",count:5,dataId:"Black"},{name:"Blue",count:14,dataId:"Blue"}],size_Filter:[{name:"10",count:16,dataId:"10"},{name:"12",count:16,dataId:"12"}]};
const output = Object.entries(myFilters)
.map(([k,arr]) => `${k}=${arr.map(a => a.name)}`)
.join("/")
console.log(output)

JavaScript Mapping Object To Array

I would like to convert objects in JavaScript, but I'm not really sure of the best way to do it. I don't often code in the language so I don't really know much of the fundamentals- this is the object I get back from an API call in a React project:
{
"api": {
"results": 380,
"fixtures": [
{
"fixture_id": 65,
"league_id": 2,
"league": {
"name": "Premier League",
"country": "England",
"logo": "https://media.api-sports.io/football/leagues/2.png",
"flag": "https://media.api-sports.io/flags/gb.svg"
},
"event_date": "2018-08-10T19:00:00+00:00",
"event_timestamp": 1533927600,
"firstHalfStart": 1533927600,
"secondHalfStart": 1533931200,
"round": "Regular Season - 1",
"status": "Match Finished",
"statusShort": "FT",
"elapsed": 90,
"venue": "Old Trafford (Manchester)",
"referee": null,
"homeTeam": {
"team_id": 33,
"team_name": "Manchester United",
"logo": "https://media.api-sports.io/football/teams/33.png"
},
"awayTeam": {
"team_id": 46,
"team_name": "Leicester",
"logo": "https://media.api-sports.io/football/teams/46.png"
},
"goalsHomeTeam": 2,
"goalsAwayTeam": 1,
"score": {
"halftime": "1-0",
"fulltime": "2-1",
"extratime": null,
"penalty": null
}
}
]
}
}
I would like to convert it to this array (the array holds multiple objects):
[
{
"homeTeam": {
"id": 33,
"name": "Manchester United",
"teamId": 33
},
"awayTeam": {
"id": 46,
"name": "Leicester",
"teamId": 46
},
"outcome": {
"goalsScoredByAwayTeam": 2,
"goalsScoredByHomeTeam": 1
},
"resulted": true,
"type": "LEAGUE"
}
]
The teamId and id actually need to lookup another object before the final output.
I'm not sure what the best way to do it is. This is my function so far, trying to make use of optional chaining:
function convertFixturesToArray() {
fixturesStore.getFixtures()?.api?.fixtures?.length ? fixtures.api.fixtures.map(fixture => (
//TRANSFORMATION GOES IN HERE
)) : null;
}
You seem on the right track. It should be something like this (written in a slightly more modern JS)
convertFixturesToArray = () => fixturesStore.getFixtures()?.api?.fixtures?.map?.(fixture => {
//Do whatever check you need here with the fixture object
return {
homeTeam: { ...fixture.homeTeam },
awayTeam: { ...fixture.awayTeam },
outcome: {
goalsScoredByAwayTeam: fixture.goalsAwayTeam,
goalsScoredByHomeTeam: fixture.goalsHomeTeam,
},
type: 'LEAGUE',
resulted: true,
},
}) ?? [];
It looks like you're trying to get certain key/value pairs from your api response. With a mix of map, reduce, and find, you can get the values you're looking for by defining them in an array (i.e. desiredProps).
Of course, adding the "outcome" field and your other hardcoded fields would require a bit more logic on top of this. Boris' answer addresses this problem. I've taken a more flexible approach.
let apiResult = {
"fixtures": [
{
"prop1": "a1",
"prop2": "a2",
"prop3": "a3"
},
{
"prop1": "b1",
"prop2": "b2",
"prop3": "b3"
}
]
}
let desiredProps = ["prop2", "prop3"]
let result = apiResult.fixtures.map(x => {
return Object.keys(x).reduce((acc, curr) => {
if (desiredProps.find(y => y === curr)) {
acc[curr] = x[curr]
}
return acc
}, {})
})
console.log(result)

Retrieve data from nested arrays

How can I retrieve ids from a nested array?
Initially I get such json response and I need to get all ids from all nested arrays.
Anybody can help me out here?
Should I use filter or any of find functions?
An example or explanation could be great.
{
"id": 271,
"name": "anything",
"description": null,
"entries": [
{
"id": "fda2afe0-dfc4-4373-9e50-8b140a46f25e",
"name": "first occurence",
"runs": [
{
"id": 284,
"name": "the element from which I want to get id",
"description": null,
"created_on": 1530627823,
"created_by": 2
},
{
"id": 285,
"name": "element for id 2",
"created_by": 2
},
{
"id": 296,
"name": "element for id 3",
"created_on": 1530710993,
"created_by": 2
}
]
},
{
"id": "a65dd3f0-3fc1-4f93-9123-f5a05ae50703",
"name": "second occurence",
"runs": [
{
"id": 272,
"name": "element for id 4",
"created_by": 2,
},
{
"id": 273,
"created_by": 2,
},
{
"id": 274,
"created_by": 2,
}
]
}
]
}
Assuming you're looking for the deepest IDs (Run IDs), here is an example of how it can be done.
let response = {"id":271,"name":"anything","description":null,"entries":[{"id":"fda2afe0-dfc4-4373-9e50-8b140a46f25e","name":"first occurence","runs":[{"id":284,"name":"the element from which I want to get id","description":null,"created_on":1530627823,"created_by":2},{"id":285,"name":"element for id 2","created_by":2},{"id":296,"name":"element for id 3","created_on":1530710993,"created_by":2}]},{"id":"a65dd3f0-3fc1-4f93-9123-f5a05ae50703","name":"second occurence","runs":[{"id":272,"name":"element for id 4","created_by":2,},{"id":273,"created_by":2,},{"id":274,"created_by":2,}]}]}
function getRunIDs() {
let entries = response['entries'] || []
let runIDs = []
entries.forEach(entry => {
entry['runs'].forEach(run => {
runIDs.push(run['id'])
})
})
return runIDs
}
console.log({ runIDs: getRunIDs() })
Assuming you store that json in some variable, say json,
const ids = json.entries.map(entry => entry.runs.map(run => run.id));
should give you a nested array of the IDs that looks like
[ [ 284, 285, 296 ], [ 272, 273, 274 ] ].
If you wanted this to be in a single dimension list, i.e.
[ 284, 285, 296, 272, 273, 274 ],
you can use concat.apply.
const concatIds = [].concat.apply([], ids);
Filter and find functions would be redundant because you are obtaining all the ids and not specific ones. To solve your problem you can simply just use functions with map . For this example, your object will be called exampleObj in which you can simply do this to get the array of all ids:
exampleObj.entries.map(entryObj => {
return entryObj.runs.map(runObj=>{return runObj.id});
});

How to remove certain key value pairs form a Object

I have used Lodash to get to this structure where i needed to group by id .
The grouping by works fine but i want to add more properties to the head of the group by field like its name and domain, from the nested object , how do i do that.
Extra - Also In future if i need to Filter the contents inside the nested object like using status or by the publisher name how do i add that . Very new to Javascript
let result = _.chain(value)
.groupBy('pubId')
.pairs()
.map(function(currentItem) {
return _.object(_.zip(['publisherId', 'targetting'], currentItem));
})
.value();
The data returned by this
{
"publisherId": "17",
// add name , domain , here
"targetting": [
{
"id": 1,
"pubId": 17, // remove this
"type": 18,
"value": "google.com,yahoo.com",
"status": 12,
"createTs": null, // remove this
"updateTs": null,// remove this
"createUser": null,// remove this
"updateUser": null,// remove this
"percentage": 0,// remove this
"rtbSspPublishers": { // remove this
"id": 17,
"name": "Tom's Hardware",
"domain": "www.tomshardware.com",
"extPublisherId": 17
}
},
{
"id": 2,
"pubId": 17,
"type": 14,
"value": "Sports,Fashion",
"status": 12,
"createTs": null,
"updateTs": null,
"createUser": null,
"updateUser": null,
"percentage": 0,
"rtbSspPublishers": {
"id": 17,
"name": "Tom's Hardware",
"domain": "www.tomshardware.com",
"extPublisherId": 17
}
},
{
"id": 3,
"pubId": 17,
"type": 11,
"value": "Sports,Fashion",
"status": 12,
"createTs": null,
"updateTs": null,
"createUser": null,
"updateUser": null,
"percentage": 0,
"rtbSspPublishers": {
"id": 17,
"name": "Tom's Hardware",
"domain": "www.tomshardware.com",
"extPublisherId": 17
}
}
]
}
I need to remove certain properties from the nested grouping how do i acheive that using lodash i am using lodash 3.0.0 .Please help thanks
Just iterate the result again and delete those properties which are not required.
For example
var propsToBeDeleted = [ "createTs", "updateTs" ]; //array of properties to be deleted
result = result.map( function(item){
propsToBeDeleted.forEach( function(prop){
delete item[prop];
});
return item;
});
Or try updating your lodash code as
let result = _.chain(value)
.groupBy('pubId')
.pairs()
.map(function(currentItem) {
var item = _.object(_.zip(['publisherId', 'targetting'], currentItem));
propsToBeDeleted.forEach( function(prop){
delete item[prop];
});
return item;
})
.value();

Join JSON Object member string values together

"category": [{
"id": 28,
"name": "Dogs"
},
{
"id": 14,
"name": "Cats"
},
{
"id": 878,
"name": "Sheep"
}],
I have the above JSON parsed (using .ajax and jsonp as callback) and I would like to join all the values of "name" into a string. i.e. "Dogs, Cats, Sheep". How can I do this? I have tried simple join on "category" and name, i.e.
var cats = categories.join(", ");
OR
var cats = categories.name.join(", ");
But since we are looking at it's members and their string values, it doesn't work.
This looks like a job for $.map!
var data = {
"category": [{
"id": 28,
"name": "Dogs"
},
{
"id": 14,
"name": "Cats"
},
{
"id": 878,
"name": "Sheep"
}]
}
var cats = $.map(data.category, function(v){
return v.name;
}).join(', ');
var text = "";
for(var i=0; category.length; i++)
{
text += category[i].name;
if(i!=category.length-1)
text += ", ";
}
Simpler, shorter version:
const category = [{
"id": 28,
"name": "Dogs"
},
{
"id": 14,
"name": "Cats"
},
{
"id": 878,
"name": "Sheep"
}]
let cats = category.map((item) => {
return item.name;
}).join(", ");
On the first part, the map function will return a string array with the contents item.name.
[ "Dogs", "Cats", "Sheep" ]
Since on arrays we have the ability to call join that will put all the items in array together but separated by whatever we pass to the join (in this case we have ", " it will separate by a comma and a space)
In the end we have:
Dogs, Cats, Sheep

Categories