Creating a new array with all the elements of subarray - javascript

I want to create an output array which takes all the parameters from its subarray and create a resulting array.
Hard to explain in words, so am explaining with an example below.
var myArr=[
{
"Id":1,
"Name":'Ken',
"Age" : '30',
"Hobbies" : [{'HobbyId':1,'HobbyName':'Swimming'},{'HobbyId':2,'HobbyName':'Reading'}],
"Skills" : [{'SkillId':1,'SkillName':'PHP'},{'SkillId':2,'SkillName':'MySQL'}],
"Language" : [{'LangId':2,'LangName':'English'},{'LangId':3,'LangName':'Chinese'}]
},
{
"Id":2,
"Name":'Mike',
"Age" : '20',
"Hobbies" : [],
"Skills" : [],
"Language" : []
},
{
"Id":3,
"Name":'Charlie',
"Age" : '25',
"Hobbies" : [{'HobbyId':5,'HobbyName':'Dance'},{'HobbyId':6,'HobbyName':'Sing'},{'HobbyId':7,'HobbyName':'Writing'}],
"Skills" : [],
"Language" : [{'Id':7,'Name':'English'}]
}
]
In the above example there are 3 subarrays named Hobbies, Skills and Languages.
I'll have some more subarrays apart from these three.
I actually want to remove the subarray logic and make it a flat array.
So, when creating this flat array I want to consider all the parameters from subarray even if the subarray is empty.
So my first item of resulting array will have the first item of all subarrays and so on.
Even if the subarray is an empty array I need to consider there keys and input the value as null.
And so my resulting array will be as below :
var resultArray = [
{
"Id":1,
"Name":'Ken',
"Age" : '30',
"HobbyId" : 1,
"HobbyName" : 'Swimming',
"SkillId" : 1,
"SkillName":'PHP',
"LangId" : 2,
"LangName" : 'English'
},
{
"Id":1,
"Name":'Ken',
"Age" : '30',
"HobbyId" : 2,
"HobbyName" : 'Reading',
"SkillId" : 2,
"SkillName":'MySQL',
"LangId" : 3,
"LangName" : 'Chinese'
},
{
"Id":2,
"Name":'Mike',
"Age" : '20',
"HobbyId" : '',
"HobbyName" : '' ,
"SkillId" : '',
"SkillName":'',
"LangId" : '',
"LangName" : ''
},
{
"Id":3,
"Name":'Charlie',
"Age" : '25',
"HobbyId" : 5,
"HobbyName" : 'Dance',
"SkillId" : '',
"SkillName":'',
"LangId" : 7,
"LangName" : 'English'
},
{
"Id":3,
"Name":'Charlie',
"Age" : '25',
"HobbyId" : 6,
"HobbyName" : 'Sing',
"SkillId" : '',
"SkillName":'',
"LangId" : '',
"LangName" : ''
},
{
"Id":3,
"Name":'Charlie',
"Age" : '25',
"HobbyId" : 7,
"HobbyName" : 'Writing',
"SkillId" : '',
"SkillName":'',
"LangId" : '',
"LangName" : ''
}
]

This seems to produce what you wanted:
let results = [];
for(let {Id, Name, Age, Hobbies, Skills, Language} of myArr) {
let numRows = Math.max(1, Hobbies.length, Skills.length, Language.length);
for (let i=0; i<numRows; i++) {
let {HobbyId, HobbyName} = Hobbies[i] || {};
let {SkillId, SkillName} = Skills[i] || {};
let {LangId, LangName} = Language[i] || {};
results.push({
Id, Name, Age,
HobbyId, HobbyName,
SkillId, SkillName,
LangId, LangName,
});
}
}
console.table(results);
The non-trivial bits are:
I use quite a bit of ES6 syntax. You might want to read a bit more about object destructuring, shorthand object literals and for..of.
I calculate the number of rows needed before starting iteration so that I don't have to check every time whether I should go to the next person or not.
I do Hobbies[i] || {} in order to make sure that I always have an object to desctructure with let {HobbyId, HobbyName}. I do it this way because it's simpler than checking for null each time.

Related

Fetching records from inside a JSON Object inside an Array

I have an API response coming in this format.
[{
"response_data": {
"0":{
"id" : 0,
"office" : "India",
"type" : 'Perm'
},
"1":{
id : 0,
"office" : "America",
"type" : 'Perm'
},
"2":{
id : 0,
"office" : "Europe",
"type" : 'Contract'
},
"2":{
id : 0,
"office" : "Latin America",
"type" : 'Contract'
}
}}]
I am trying to get all the office where the type is Contract. I have the json response saved in a variable like - using Chakram as
var response_json = t.body[0].response_data;
which gives me correct response in the console.log as
"0":{
"id" : 0,
"office" : "India",
"type" : 'Perm'
},
"1":{
id : 0,
"office" : "America",
"type" : 'Perm'
},
"2":{
id : 0,
"office" : "Europe",
"type" : 'Contract'
},
"2":{
id : 0,
"office" : "Latin America",
"type" : 'Contract'
}
Now how to get to the corresponding keys in inside the json and extract the information required. I tried this but it returns undefined
var length = Object.keys(response_json).length;
for(var i = 0; i<= length;i++){
console.log(response_json.i) //returns undefined
console.log((Object.keys(response_json)).id); //returns undefined.
}
I know that this can be solved using filter method if the response was an array, but how can I do the same operation in JSON object? I am looking for an optimized solution because the API returns almost 5000 objects.
If this question has already been asked, provide reference since I was not able to find any on SO.
If you want to do this with filter method then
a workaround would be to add a property length then using Array.from like below. Then you can use Array.prototype.filter method.
let o = {
'0': {
id: 0,
"office": "India",
"type": 'Perm'
},
'1': {
id: 0,
"office": "America",
"type": 'Perm'
},
'2': {
id: 0,
"office": "Europe",
"type": 'Contract'
}
};
o.length = Object.keys(o).length;
let a = Array.from(o);
let r = a.filter(({ type }) => type == 'Contract');
console.log(r);
Two major mistakes your code have one using loop up to the length of an array where index starts from 0. and second accessing an object from an array you use brackets instead of the dot. So update the code as follows:
var keys = Object.keys(response_json);
var length = keys .length;
for(var i = 0; i< length;i++){
console.log(response_json[keys[i]]);
}
On your response_json '0' , '1' all keys are in string format.
But in your for loop 'i' is integer so key is unavailable. just convert it to string you can get desired result
like console.log(response_json[''+i])
var data = [{"response_data": {
'0':{id : 0, "office" : "India", "type" : 'Perm'},
'1':{id : 0, "office" : "America","type" : 'Perm'},
'2':{ id : 0, "office" : "Europe","type" : 'Contract'},
'3':{ id : 0, "office" : "Latin America", "type" : 'Contract'}
}}];
var list = data[0]['response_data'];
var filterList = [];
for(var i in list) {
if(list.hasOwnProperty(i)) {
var type = list[i]['type'];
if(type === 'Contract') {
filterList.push(list[i]);
}
}
}
May be not better in javascript if the record is more than 5 thousand, better process it on server side.

How to perform sort in array of objects in one record in mongoose [duplicate]

This question already has answers here:
How to sort array inside collection record in MongoDB?
(16 answers)
Closed 4 years ago.
I want to fetch the data by sorting xm_score but it's not working with my query.
query = match.find({ '_id': 'k00012' }).sort('npi.xm_score');
I need to get the objects in npi get sorted by xm_score in this array.
I have the data as follows,
{
"term":'k00012',
"npi" : [
{
"npi" : "1003000126",
"xm_score" : 77.1,
"geo" : [
-75.53091147,
40.60619643
],
"state" : "PA",
"zip" : "18103",
"specialty" : [
"x010"
]
},
{
"npi" : "1003000126",
"xm_score" : 70.1,
"geo" : [
-75.53091147,
40.60619643
],
"state" : "PA",
"zip" : "18103",
"specialty" : [
"x010"
]
}]
}
You can simply have a custom function for sorting array
let obj = {
"term":'k00012',
"npi" : [
{
"npi" : "1003000126",
"xm_score" : 77.1,
"geo" : [
-75.53091147,
40.60619643
],
"state" : "PA",
"zip" : "18103",
"specialty" : [
"x010"
]
},
{
"npi" : "1003000126",
"xm_score" : 70.1,
"geo" : [
-75.53091147,
40.60619643
],
"state" : "PA",
"zip" : "18103",
"specialty" : [
"x010"
]
}]
}
let arr = obj.npi;
arr.sort((a,b) => {
return a.xm_score - b.xm_score
})
console.log(arr)

Accumulate scores

I have an array of objects in the form below. Each object represents the result of a soccer game. The actual array contains far more records than what I have here. In each game, the team (home or away) that has the highest corresponding score gets 3 points and the team with the lowest score gets 0 points. If the scores are the same, each team gets 1 point. I want to create logic that aggregates the points for each unique team whether they are home or away. I would like to see different types of options (newer syntax, etc), but especially a vanilla javascript solution.
I plan to work through it as well, but I'm struggling to come up with anything succinct.
[{
"_id" : ObjectId("5a4824f3a469a068edc875e2"),
"homeTeam" : "Team1",
"homeScore" : 2,
"awayTeam" : "Team2",
"awayScore" : 1,
}
{
"_id" : ObjectId("5a4824f3a469a068edc894e9"),
"homeTeam" : "Team2",
"homeScore" : 2,
"awayTeam" : "Team3",
"awayScore" : 1,
},{
"_id" : ObjectId("5a4824f3a469a068edc554e7"),
"homeTeam" : "Team4",
"homeScore" : 1,
"awayTeam" : "Team5",
"awayScore" : 1,
}]
var data = [{
"_id" : "5a4824f3a469a068edc875e2",
"homeTeam" : "Team1",
"homeScore" : 2,
"awayTeam" : "Team2",
"awayScore" : 1,
},
{
"_id" : "5a4824f3a469a068edc894e9",
"homeTeam" : "Team2",
"homeScore" : 2,
"awayTeam" : "Team3",
"awayScore" : 1,
},{
"_id" : "5a4824f3a469a068edc554e7",
"homeTeam" : "Team4",
"homeScore" : 1,
"awayTeam" : "Team5",
"awayScore" : 1,
}];
var teamStats = {};
var i = 0;
for(;i < data.length; i++) {
// New Home team
if(teamStats[data[i].homeTeam] == undefined) {
teamStats[data[i].homeTeam] = {
name: data[i].homeTeam,
score: 0
}
}
// New Away team
if(teamStats[data[i].awayTeam] == undefined) {
teamStats[data[i].awayTeam] = {
name: data[i].awayTeam,
score: 0
}
}
// Update score
teamStats[data[i].homeTeam].score += data[i].homeScore;
teamStats[data[i].awayTeam].score += data[i].awayScore;
}
// teamStats contains a scores of all teams

Group Array into a more complex Array

I create an array of Objects from a database query and call the
array jobListRecords. There are multiple records in the array created that have the same "customerID" and "name".
I would like to create a new array that has one record for each customer with a new field , "jobArray", that contains another array of all of that customers services. (see sortCustomer array down below)
An example of the initial array:
jobListRecords = [
{
"customerID" : "1",
"name" : "Larry Bird",
"serviceID" : "101",
"serviceName" : "Dog Walking"
},
{
"customerID" : "2",
"name" : "Andrew Luck",
"serviceID" : "202",
"serviceName" : "Baby Sitting"
},
{
"customerID" : "2",
"name" : "Andrew Luck",
"serviceID" : "101",
"serviceName" : "Dog Walking"
}
]
Desired Result
sortCustomer Example:
sortCustomer = [
{
"customerID" : "1",
"name" : " Larry Bird",
"jobArray" : [
{
"serviceID" : "101",
"serviceName" : "Dog Walking"
}
]
},
{
"customerID" : "2",
"name" : "Andrew Luck",
"jobArray" : [
{
"serviceID" : "202",
"serviceName" : "Baby Sitting"
},
{
"serviceID" : "101",
"serviceName" : "Dog Walking"
}
]
}
Is their a simple or efficient way of solving this without having to iterate through all the data 3+ times. Thank You for your time, below is one of the several things I tried.
I tried solving this using one example I found but it grouped all the serviceIDs together which is not what I need.
Example that DID NOT work that I tried.
jobListGrouped = _
.chain(jobListRecords)
.groupBy('customerID')
.map(function(value, key) {
return {
CustomerID: key,
services: _.pluck(value, 'serviceID')
}
})
.value();
You're plucking only the serviceIDs into that array. Instead, you would need to do something like
.map(function(values, key) {
return {
customerID: key,
name: values[0].name.
services: _.map(values, _.partial(_.pick, _, 'serviceID', 'serviceName'))
}
})
or even more explicit
.map(function(values, key) {
return _.extend(_.omit(values[0], 'serviceID', 'serviceName'), {
services: _.map(values, _.partial(_.pick, _, 'serviceID', 'serviceName'))
}
})
(where that partial call is the same as function(value) { return _.pick(value, 'serviceID', 'serviceName'); })

Using angular foreach loop to rearrange JSON

I have an ng-repeat which returns arrays of objects like the following:
[{"day":"10","title":"day","summary":"summary","description":"ok","_id":"53f25185bffedb83d8348b22"}]
[{"day":"3","title":"day","summary":"summary","description":"ok","_id":"53f25185bffedb83d8348b22"}]
I'd like to have pull out the objects and push them into another array so they are formatted like this:
[
{"day":"10","title":"day","summary":"summary","description":"ok","_id":"53f25185bffedb83d8348b22"},
{"day":"3","title":"day","summary":"summary","description":"ok","_id":"53f25185bffedb83d8348b22"
}]
The goal is to use an orderBy on the array. Is it possible to restructure the JSON into this format and then access the data?
Here is my view for reference:
<div class="calDynamic" data-ng-repeat="n in [] | range:100">
<div ng-repeat="cal in calendar[n].year | filterKey:month">
<p>{{cal}}</p>
</div>
</div>
My JSON format:
{
"_id" : ObjectId("53f252537d343a9ad862866c"),
"year" : {
"December" : [],
"November" : [],
"October" : [],
"September" : [],
"August" : [],
"July" : [
{
"day" : "21",
"title" : "u",
"summary" : "u",
"description" : "ok",
"_id" : ObjectId("53f252537d343a9ad862866d")
}
],
"June" : [],
"May" : [],
"April" : [],
"March" : [],
"February" : [],
"January" : []
},
"__v" : 0
},
{
"_id" : ObjectId("53f252537d343a9ad862866c"),
"year" : {
"December" : [],
"November" : [],
"October" : [],
"September" : [],
"August" : [],
"July" : [
{
"day" : "3",
"title" : "u",
"summary" : "u",
"description" : "ok",
"_id" : ObjectId("53f252537d343a9ad862866d")
}
],
"June" : [],
"May" : [],
"April" : [],
"March" : [],
"February" : [],
"January" : []
},
"__v" : 0
}
Just elaborating my comment to answer:-
You can do this way to merge the arrays scattered across various month to 1 array.
//obj has the the array result that is the input
var temp = [];
var result = temp.concat.apply(temp,obj.map(function(itm){ //Get each object in the source array that hold the year.
return temp.concat.apply(temp, Object.keys(itm.year).map(function(key){ //Get Month for each yeah and flatten it out
return itm.year[key]; //Get day array for each of the month in each year
}));
}));
Object.keys(obj.year) ==> Will give you the months in your property Year to an array
Array.prototype.map ==> You pass in the months array and get back 2D array of days from all of months.
[].concat ==> returns array of concatenated arrays. It can take multiple arrays are argument, so we use function.apply conveniently to convert 2D to 1D.
Bin
Other simple and performance effective way always is loop through and add upon.
Array.prototype.concat allows to join two arrays into one. However, it is just javascript and has nothing to do with Angular, the way to do it is like:
var a = [{"day":"10","title":"day","summary":"summary","description":"ok","_id":"53f25185bffedb83d8348b22"}];
var b = [{"day":"3","title":"day","summary":"summary","description":"ok","_id":"53f25185bffedb83d8348b22"}];
var c = a.concat(b); // returns the concatenated array.

Categories