Penetrate a JSON response by object value - javascript

I'm receiving following JSON response from our servers and my requirement is to display the servlet details.
if(dataStoreLogFileSize > 10 && "dataStoreLogLevel": "production".)
I have written following Javacript code snippet to penetrate the JSON by those values But it is not working properly. Can anyone help me with this please.
{
"web-app": {
"servlet": [{
"servlet-name": "cofaxCDS",
"servlet-class": "org.cofax.cds.CDSServlet",
"init-param": {
"configGlossary:installationAt": "Philadelphia, PA",
"configGlossary:adminEmail": "ksm#pobox.com",
"configGlossary:poweredBy": "Cofax",
"configGlossary:poweredByIcon": "/images/cofax.gif",
"configGlossary:staticPath": "/content/static",
"templateProcessorClass": "org.cofax.WysiwygTemplate",
"templateLoaderClass": "org.cofax.FilesTemplateLoader",
"templatePath": "templates",
"templateOverridePath": "",
"defaultListTemplate": "listTemplate.htm",
"defaultFileTemplate": "articleTemplate.htm",
"useJSP": false,
"jspListTemplate": "listTemplate.jsp",
"jspFileTemplate": "articleTemplate.jsp",
"searchEngineListTemplate": "forSearchEnginesList.htm",
"searchEngineFileTemplate": "forSearchEngines.htm",
"searchEngineRobotsDb": "WEB-INF/robots.db",
"useDataStore": true,
"dataStoreClass": "org.cofax.SqlDataStore",
"redirectionClass": "org.cofax.SqlRedirection",
"dataStoreName": "cofax",
"dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver",
"dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
"dataStoreUser": "sa",
"dataStorePassword": "dataStoreTestQuery",
"dataStoreTestQuery": "SET NOCOUNT ON;select test='test';",
"dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log",
"dataStoreInitConns": 10,
"dataStoreLogFileSize": 10,
"dataStoreMaxConns": 100,
"dataStoreConnUsageLimit": 100,
"dataStoreLogLevel": "production",
"maxUrlLength": 500
}
},
{
"servlet-name": "cofaxTools",
"servlet-class": "org.cofax.cms.CofaxToolsServlet",
"init-param": {
"templatePath": "toolstemplates/",
"log": 1,
"logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
"logMaxSize": "",
"dataLog": 1,
"dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
"dataLogMaxSize": "",
"removePageCache": "/content/admin/remove?cache=pages&id=",
"removeTemplateCache": "/content/admin/remove?cache=templates&id=",
"fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder",
"lookInContext": 1,
"adminGroupID": 4,
"betaServer": true,
"dataStoreInitConns": 10,
"dataStoreLogFileSize": 5,
"dataStoreMaxConns": 100,
"dataStoreConnUsageLimit": 100,
"dataStoreLogLevel": "test",
"maxUrlLength": 500
}
}
],
"servlet-mapping": {
"cofaxCDS": "/",
"cofaxEmail": "/cofaxutil/aemail/*",
"cofaxAdmin": "/admin/*",
"fileServlet": "/static/*",
"cofaxTools": "/tools/*"
},
"taglib": {
"taglib-uri": "cofax.tld",
"taglib-location": "/WEB-INF/tlds/cofax.tld"
}
}
}
+********************************************************************************+
//Some code above
let foo = data.filter(object => (object.dataStoreLogLevel === 'production'
&& object => (object.dataStoreLogFileSize > '10');
console.log('Servlet Details Test' + foo);
//Code continues

You can use this code to get dataStoreLogFileSize greater than 1gb and production dataStoreLogLevel.
const jsoncode = {
"web-app": {
servlet: [
{
"servlet-name": "cofaxCDS",
"servlet-class": "org.cofax.cds.CDSServlet",
"init-param": {
"configGlossary:installationAt": "Philadelphia, PA",
"configGlossary:adminEmail": "ksm#pobox.com",
"configGlossary:poweredBy": "Cofax",
"configGlossary:poweredByIcon": "/images/cofax.gif",
"configGlossary:staticPath": "/content/static",
templateProcessorClass: "org.cofax.WysiwygTemplate",
templateLoaderClass: "org.cofax.FilesTemplateLoader",
templatePath: "templates",
templateOverridePath: "",
defaultListTemplate: "listTemplate.htm",
defaultFileTemplate: "articleTemplate.htm",
useJSP: false,
jspListTemplate: "listTemplate.jsp",
jspFileTemplate: "articleTemplate.jsp",
searchEngineListTemplate: "forSearchEnginesList.htm",
searchEngineFileTemplate: "forSearchEngines.htm",
searchEngineRobotsDb: "WEB-INF/robots.db",
useDataStore: true,
dataStoreClass: "org.cofax.SqlDataStore",
redirectionClass: "org.cofax.SqlRedirection",
dataStoreName: "cofax",
dataStoreDriver: "com.microsoft.jdbc.sqlserver.SQLServerDriver",
dataStoreUrl:
"jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
dataStoreUser: "sa",
dataStorePassword: "dataStoreTestQuery",
dataStoreTestQuery: "SET NOCOUNT ON;select test='test';",
dataStoreLogFile: "/usr/local/tomcat/logs/datastore.log",
dataStoreInitConns: 10,
dataStoreLogFileSize: "1GB",
dataStoreMaxConns: 100,
dataStoreConnUsageLimit: 100,
dataStoreLogLevel: "production",
maxUrlLength: 500
}
},
{
"servlet-name": "cofaxTools",
"servlet-class": "org.cofax.cms.CofaxToolsServlet",
"init-param": {
templatePath: "toolstemplates/",
log: 1,
logLocation: "/usr/local/tomcat/logs/CofaxTools.log",
logMaxSize: "",
dataLog: 1,
dataLogLocation: "/usr/local/tomcat/logs/dataLog.log",
dataLogMaxSize: "",
removePageCache: "/content/admin/remove?cache=pages&id=",
removeTemplateCache: "/content/admin/remove?cache=templates&id=",
fileTransferFolder:
"/usr/local/tomcat/webapps/content/fileTransferFolder",
lookInContext: 1,
adminGroupID: 4,
betaServer: true,
dataStoreInitConns: 10,
dataStoreLogFileSize: "0.5GB",
dataStoreMaxConns: 100,
dataStoreConnUsageLimit: 100,
dataStoreLogLevel: "test",
maxUrlLength: 500
}
}
],
"servlet-mapping": {
cofaxCDS: "/",
cofaxEmail: "/cofaxutil/aemail/*",
cofaxAdmin: "/admin/*",
fileServlet: "/static/*",
cofaxTools: "/tools/*"
},
taglib: {
"taglib-uri": "cofax.tld",
"taglib-location": "/WEB-INF/tlds/cofax.tld"
}
}
};
// jsoncode is your json response from server
const final = jsoncode['web-app'].servlet.filter((s) => {
// get the number from dataStoreLogFileSize
const size = s['init-param'].dataStoreLogFileSize.replace(/[^0-9\.]+/g, '');
// make sure the size is a number by adding a plus sign
return +size >= 1 && s['init-param'].dataStoreLogLevel === 'production';
});
console.log(final);

you're filtering the wrong array, the one having dataStoreLogLevel and dataStoreLogFileSize is in data['web-app'][0]['servlet']['init-param'], so you need to apply .filter on the data['web-app'].servlet array.
For the fileSize you'll need to use parseFloat to extract the size since it's a string.
You need to fix the .filter syntax.
and use , to console.log the result :
const data = {
"web-app": {
"servlet": [{
"servlet-name": "cofaxCDS",
"servlet-class": "org.cofax.cds.CDSServlet",
"init-param": {
"configGlossary:installationAt": "Philadelphia, PA",
"configGlossary:adminEmail": "ksm#pobox.com",
"configGlossary:poweredBy": "Cofax",
"configGlossary:poweredByIcon": "/images/cofax.gif",
"configGlossary:staticPath": "/content/static",
"templateProcessorClass": "org.cofax.WysiwygTemplate",
"templateLoaderClass": "org.cofax.FilesTemplateLoader",
"templatePath": "templates",
"templateOverridePath": "",
"defaultListTemplate": "listTemplate.htm",
"defaultFileTemplate": "articleTemplate.htm",
"useJSP": false,
"jspListTemplate": "listTemplate.jsp",
"jspFileTemplate": "articleTemplate.jsp",
"searchEngineListTemplate": "forSearchEnginesList.htm",
"searchEngineFileTemplate": "forSearchEngines.htm",
"searchEngineRobotsDb": "WEB-INF/robots.db",
"useDataStore": true,
"dataStoreClass": "org.cofax.SqlDataStore",
"redirectionClass": "org.cofax.SqlRedirection",
"dataStoreName": "cofax",
"dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver",
"dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
"dataStoreUser": "sa",
"dataStorePassword": "dataStoreTestQuery",
"dataStoreTestQuery": "SET NOCOUNT ON;select test='test';",
"dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log",
"dataStoreInitConns": 10,
"dataStoreLogFileSize": "1GB",
"dataStoreMaxConns": 100,
"dataStoreConnUsageLimit": 100,
"dataStoreLogLevel": "production",
"maxUrlLength": 500
}
},
{
"servlet-name": "cofaxTools",
"servlet-class": "org.cofax.cms.CofaxToolsServlet",
"init-param": {
"templatePath": "toolstemplates/",
"log": 1,
"logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
"logMaxSize": "",
"dataLog": 1,
"dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
"dataLogMaxSize": "",
"removePageCache": "/content/admin/remove?cache=pages&id=",
"removeTemplateCache": "/content/admin/remove?cache=templates&id=",
"fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder",
"lookInContext": 1,
"adminGroupID": 4,
"betaServer": true,
"dataStoreInitConns": 10,
"dataStoreLogFileSize": "0.5GB",
"dataStoreMaxConns": 100,
"dataStoreConnUsageLimit": 100,
"dataStoreLogLevel": "test",
"maxUrlLength": 500
}
}
],
"servlet-mapping": {
"cofaxCDS": "/",
"cofaxEmail": "/cofaxutil/aemail/*",
"cofaxAdmin": "/admin/*",
"fileServlet": "/static/*",
"cofaxTools": "/tools/*"
},
"taglib": {
"taglib-uri": "cofax.tld",
"taglib-location": "/WEB-INF/tlds/cofax.tld"
}
}
}
let foo = data['web-app'].servlet.filter(
object =>
object['init-param'].dataStoreLogLevel === 'production'
&& parseFloat(object['init-param'].dataStoreLogFileSize) >= 1 // change this to 10 for fileSize >= 10GB
);
console.log('Servlet Details Test', foo);

Related

prebid.js ad is not getting rendered

I have setup prebid.js with single adaptor configured on test page. I am getting the ad response from adaptor and I can see the pbjs.getBidResponses() object is present still ad is not getting rendered on the page.
you can visit test page
standard prebid setup as follows
JAVSCRIPT
var sizes = [
[300, 250]
];
var PREBID_TIMEOUT = 1000;
var FAILSAFE_TIMEOUT = 3000;
var adUnits = [{
code: '/19968336/header-bid-tag-1',
mediaTypes: {
banner: {
sizes: sizes
}
},
bids: [{
bidder: 'incrementx',
params: {
placementId: 'PNX-HB-R787915V41024E'
}
}]
}];
// ======== DO NOT EDIT BELOW THIS LINE =========== //
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
googletag.cmd.push(function () {
googletag.pubads().disableInitialLoad();
});
var pbjs = pbjs || {};
pbjs.que = pbjs.que || [];
pbjs.que.push(function () {
pbjs.addAdUnits(adUnits);
pbjs.requestBids({
bidsBackHandler: initAdserver,
timeout: PREBID_TIMEOUT
});
});
function initAdserver() {
if (pbjs.initAdserverSet) return;
pbjs.initAdserverSet = true;
googletag.cmd.push(function () {
pbjs.setTargetingForGPTAsync && pbjs.setTargetingForGPTAsync();
googletag.pubads().refresh();
});
}
// in case PBJS doesn't load
setTimeout(function () {
initAdserver();
}, FAILSAFE_TIMEOUT);
googletag.cmd.push(function () {
googletag.defineSlot('/19968336/header-bid-tag-1', sizes, 'div-1')
.addService(googletag.pubads());
googletag.pubads().collapseEmptyDivs();
googletag.pubads().enableSingleRequest();
googletag.enableServices();
});
HTML
<div id='div-1'>
<script type='text/javascript'>
googletag.cmd.push(function () {
googletag.display('div-1');
});
</script>
</div>
ADAPTOR Response
{
"vzhPlacementId": "<placement-id>",
"bid": "<bid>",
"adWidth": "300",
"adHeight": "250",
"cpm": "0.017442",
"ad": "<ad-tag>",
"slotBidId": "<slot-id>",
"statusText": "Vertoz:Success"
}
pbjs.getBidResponses() output
{
"/19968336/header-bid-tag-1": {
"bids": [
{
"bidderCode": "incrementx",
"width": 300,
"height": 250,
"statusMessage": "Bid available",
"adId": "389575b4d6d5f1",
"requestId": "2b7446c2969f1f",
"transactionId": "a6a81b3e-8cf7-4d71-bc7e-34c283e1a746",
"auctionId": "4455d9a4-4364-4f9d-bd1a-d7f0a7fd56e4",
"mediaType": "banner",
"source": "client",
"cpm": 0.017442,
"currency": "USD",
"ttl": 300,
"creativeId": 0,
"netRevenue": false,
"meta": {
"mediaType": "banner",
"advertiserDomains": [],
"dchain": {
"ver": "1.0",
"complete": 0,
"nodes": [
{
"name": "incrementx"
}
]
}
},
"ad": "<ad-tag>",
"adapterCode": "incrementx",
"originalCpm": "0.017442",
"originalCurrency": "USD",
"responseTimestamp": 1656921876245,
"requestTimestamp": 1656921875927,
"bidder": "incrementx",
"adUnitCode": "/19968336/header-bid-tag-1",
"timeToRespond": 318,
"pbLg": "0.00",
"pbMg": "0.00",
"pbHg": "0.01",
"pbAg": "0.00",
"pbDg": "0.01",
"pbCg": "",
"size": "300x250",
"adserverTargeting": {
"hb_bidder": "incrementx",
"hb_adid": "389575b4d6d5f1",
"hb_pb": "0.00",
"hb_size": "300x250",
"hb_source": "client",
"hb_format": "banner",
"hb_adomain": ""
},
"status": "targetingSet"
}
]
}
}
pbjs.getAllPrebidWinningBids() & pbjs.getAllWinningBids() output
[]
this is the output I am getting
not able to find the issue, there is only 1 adaptor integrated so in all cases the bid should win, not sure am I missing something in setup?. Any help would be appreciated, thank you
Because this line is a copy from the prebid.org docs:
googletag.defineSlot('/19968336/header-bid-tag-1', sizes, 'div-1')
I don't think you have your own GAM account configured correctly.
You'll need to have a GAM account and switch the first parameter of defineSlot to be your own GAM ad unit code.
You'll want to follow the postbid instructions if you want to avoid using GAM.

undefined json field when making a get request on node.js

Im using an ocr api to scan the image. here's my get request
let request = http.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (data) {
let JSONresponce = JSON.parse(data);
console.log(JSONresponce.ParsedResults)
});
});
request.on('error', function(e) {
console.log('Cant scan the image');
});
request.end();
Here's the json structure i'm supposed to get
{
"ParsedResults" : [
{
"TextOverlay" : {
"Lines" : [
{
"Words": [
{
"WordText": "Word 1",
"Left": 106,
"Top": 91,
"Height": 9,
"Width": 11
},
{
"WordText": "Word 2",
"Left": 121,
"Top": 90,
"Height": 13,
"Width": 51
}
.
.
.
More Words
],
"MaxHeight": 13,
"MinTop": 90
},
.
.
.
.
More Lines
],
"HasOverlay" : true,
"Message" : null
},
"FileParseExitCode" : "1",
"ParsedText" : "This is a sample parsed result",
"ErrorMessage" : null,
"ErrorDetails" : null
},
{
"TextOverlay" : null,
"FileParseExitCode" : -10,
"ParsedText" : null,
"ErrorMessage" : "...error message (if any)",
"ErrorDetails" : "...detailed error message (if any)"
}
.
.
.
],
"OCRExitCode" : "2",
"IsErroredOnProcessing" : false,
"ErrorMessage" : null,
"ErrorDetails" : null
"SearchablePDFURL": "https://....." (if requested, otherwise null)
"ProcessingTimeInMilliseconds" : "3000"
}
Since im logging only ParsedResults this is what im getting
[
{
TextOverlay: {
Lines: [],
HasOverlay: false,
Message: 'Text overlay is not provided as it is not requested'
},
TextOrientation: '0',
FileParseExitCode: 1,
ParsedText: 'hello world',
ErrorMessage: '',
ErrorDetails: ''
}
]
But the only thing i need is ParsedText field. And when i try to get it either via
JSONresponce.ParsedResults.ParsedText
or
JSONresponce.ParsedResults['ParsedText']
Im getting either just undefined response or an error msg with same meaning.
Is there a way to get the ParsedText field ?
The JSON object is a array with one item. (Notice the [] characters) You need JSONresponce.ParsedResults[0]['ParsedText'] to get the first (and only) item from the array.

Dynamically create multi leveled drilldowns in Amcharts

I need to create a multi leveled that is dynamic because I have to drill down to hundreds or even thousands of data providers that will load from the database. The flow goes like this: I have 1, 2, 3, 4, and 5 years that will drill down to 16 Departments each and will drill down to Courses 10 or more courses. Doing it manually is tedious and I need it to be dynamic. Please help me.
The variables:
var ccs_final_data = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/final_ccs_data");
//VAR CCS AVERAGE_FINAL
var drill_down_to_ccs_courses_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_courses_data_average_final");
var drill_down_to_ccs_sections_BSIT_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_sections_data_BSIT_average_final");
var drill_down_to_ccs_sections_ACT_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_sections_data_ACT_average_final");
var drill_down_to_ccs_sections_BSCS_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_sections_data_BSCS_average_final");
The graph:
var chart2 = AmCharts.makeChart( "ccs2", {
"theme": "light",
type: "serial",
pathToImages: "http://cdn.amcharts.com/lib/3/images/",
dataProvider: ccs_final_data,
categoryField: "category",
categoryAxis: {
labelRotation: 0,
gridPosition: "start"
},
valueAxes: [ {
title: "CCS FINAL TERM - Passing"
} ],
graphs: [ {
valueField: "value",
colorField: "color",
type: "column",
lineAlpha: 100,
fillAlphas: 1
} ],
chartScrollbar: {
"updateOnReleaseOnly": true
},
chartCursor: {
bulletsEnabled: "enabled",
bulletSize: 15,
cursorAlpha: 100,
cursorColor: "#CC0000",
zoomable: true,
categoryBalloonEnabled: true
},
export: {
enabled: true
}
} );
Here's the drill down stuff:
chart2.addListener("clickGraphItem", function (event) {
if(event.item.category == "Average"){
event.chart.dataProvider = drill_down_to_ccs_courses_average_final;
event.chart.validateData();
chart2.addListener("clickGraphItem", function (event) {
if(event.item.category == "BSIT"){
event.chart.dataProvider = drill_down_to_ccs_sections_BSIT_average_final;
event.chart.validateData();
}
else if(event.item.category == "ACT"){
event.chart.dataProvider = drill_down_to_ccs_sections_ACT_average_final;
event.chart.validateData();
}
else if(event.item.category == "BSCS"){
event.chart.dataProvider = drill_down_to_ccs_sections_BSCS_average_final;
event.chart.validateData();
}
});
}
I'd say the best way to make it dynamic is to include some custom field for each data point in your data that would be passed in to server-side script so it knows which data to load.
I'm assuming your data looks like this now:
[ {
"category": "BSIT",
"value": 100
}, {
"category": "ACT",
"value": 200
}, {
"category": "BSCS",
"value": 150
} ]
You could easily add a third field to hold the information for drill-down data load:
[ {
"category": "BSIT",
"value": 100,
"drill": "ccs_sections_data_BSIT_average_final"
}, {
"category": "ACT",
"value": 200,
"drill": "ccs_sections_data_ACT_average_final"
}, {
"category": "BSCS",
"value": 150,
"drill": "ccs_sections_data_BSCS_average_final"
} ]
Then, when clickGraphItem event occurs, you could just take that info and pass it to load script dynamically:
chart2.addListener( "clickGraphItem", function( event ) {
if ( event.item.dataContext.drill !== undefined ) {
event.chart.dataProvider = AmCharts.loadJSON( "<?php echo base_url();?>index.php/osa/" + event.item.dataContext.drill );
event.chart.validateData();
}
} );
This way, you could have any number of drill-down levels, with each level data containing info about where to look for the data for the next level.
Also, I'm not sure as you haven't posted the code for it, so I'm assuming that AmCharts.loadJSON method is synchronous. If it's not (for example if you are using method from Data Loader), you will need to assign the chart's dataProvider after the data is loaded.

Mapping data from multiple arrays of objects to a new object in Javascript using functional programming

I am trying to create an object that requires mapping
data from four arrays included in a function. The goal
is to accomplish the new map using functional programming.
Thus, for example, the methods map, reduce, forEach, concat, and
filter would be allowed as well as custom functions.
I have arrived at a non functional solution using for-loops,
which I've included below. However, I get stuck on a purely
functional approach.
The data set and data for the desired outcome can be
viewed independently at http://jhusain.github.io/learnrx/, though I've included the data below.
The objective is to re-map the data using functional programming so that it resembles the desired output (included below).
I would appreciate help re-mapping the data using a functional approach
and starting from the data shown below.
The exact text of the problem states:
Exercise 26: Converting from Arrays to Deeper Trees
Let's try creating a deeper tree structure. This time we have 4
seperate arrays each containing lists, videos, boxarts, and bookmarks
respectively. Each object has a parent id, indicating its parent. We
want to build an array of list objects, each with a name and a videos
array. The videos array will contain the video's id, title, bookmark
time, and smallest boxart url. In other words we want to build the
following structure:
The desired output is:
[
{
"name": "New Releases",
"videos": [
{
"id": 65432445,
"title": "The Chamber",
"time": 32432,
"boxart": "http://cdn-0.nflximg.com/images/2891/TheChamber130.jpg"
},
{
"id": 675465,
"title": "Fracture",
"time": 3534543,
"boxart": "http://cdn-0.nflximg.com/images/2891/Fracture120.jpg"
}
]
},
{
"name": "Thrillers",
"videos": [
{
"id": 70111470,
"title": "Die Hard",
"time": 645243,
"boxart": "http://cdn-0.nflximg.com/images/2891/DieHard150.jpg"
},
{
"id": 654356453,
"title": "Bad Boys",
"time": 984934,
"boxart": "http://cdn-0.nflximg.com/images/2891/BadBoys140.jpg"
}
]
}
]
The function that serves as the starting point follows below.
I've named the function "combine" so that we can call it. Also, I've
included my solution, made up of for-loops, at the end of the
function after the bookmarks array. My attempt at a functional solution only
got this far:
return lists.map(function(list) {
return {
name: list.name,
videos:
videos.
filter(function(video) {
return video.listId === list.id;
}). // I got stuck at this point.
This is the starting set of data:
function combine() {
var lists = [
{
"id": 5434364,
"name": "New Releases"
},
{
"id": 65456475,
name: "Thrillers"
}
],
videos = [
{
"listId": 5434364,
"id": 65432445,
"title": "The Chamber"
},
{
"listId": 5434364,
"id": 675465,
"title": "Fracture"
},
{
"listId": 65456475,
"id": 70111470,
"title": "Die Hard"
},
{
"listId": 65456475,
"id": 654356453,
"title": "Bad Boys"
}
],
boxarts = [
{ videoId: 65432445, width: 130, height:200, url:"http://cdn-0.nflximg.com/images/2891/TheChamber130.jpg" },
{ videoId: 65432445, width: 200, height:200, url:"http://cdn-0.nflximg.com/images/2891/TheChamber200.jpg" },
{ videoId: 675465, width: 200, height:200, url:"http://cdn-0.nflximg.com/images/2891/Fracture200.jpg" },
{ videoId: 675465, width: 120, height:200, url:"http://cdn-0.nflximg.com/images/2891/Fracture120.jpg" },
{ videoId: 675465, width: 300, height:200, url:"http://cdn-0.nflximg.com/images/2891/Fracture300.jpg" },
{ videoId: 70111470, width: 150, height:200, url:"http://cdn-0.nflximg.com/images/2891/DieHard150.jpg" },
{ videoId: 70111470, width: 200, height:200, url:"http://cdn-0.nflximg.com/images/2891/DieHard200.jpg" },
{ videoId: 654356453, width: 200, height:200, url:"http://cdn-0.nflximg.com/images/2891/BadBoys200.jpg" },
{ videoId: 654356453, width: 140, height:200, url:"http://cdn-0.nflximg.com/images/2891/BadBoys140.jpg" }
],
bookmarks = [
{ videoId: 65432445, time: 32432 },
{ videoId: 675465, time: 3534543 },
{ videoId: 70111470, time: 645243 },
{ videoId: 654356453, time: 984934 }
];
//My non-functional solution
sizeArr = [];
for(var i = 0; i < lists.length; i++){
lists[i].videos = [];
for(var j = 0; j < videos.length; j++){
if(videos[j].listId === lists[i].id){
lists[i].videos.push(videos[j]);
}
for(var k = 0; k < bookmarks.length; k++){
if(bookmarks[k].videoId === videos[j].id && videos[j].listId === lists[i].id){
videos[j].time = bookmarks[k].time;
}
for(var l = 0; l < boxarts.length; l++){
var size = boxarts[l].width * boxarts[l].height;
sizeArr.push(size);
sizeArr = sizeArr.sort(function(min, max){
if(min < max){
return min;
}
if(boxarts[l].videoId === videos[j].id && videos[j].listId === lists[i].id){
videos[j].boxart = boxarts[l].url;
}
});
}
}
}
delete lists[i].id;
}
return lists;
}
combine();
This works, but it's not that efficient. You first could create dictionaries or maps from your arrays to allow quick id lookups. That would eliminate the need for filters.
I also avoided to mutate the initial data structures.
var lists = [{
"id": 5434364,
"name": "New Releases"
}, {
"id": 65456475,
name: "Thrillers"
}],
videos = [{
"listId": 5434364,
"id": 65432445,
"title": "The Chamber"
}, {
"listId": 5434364,
"id": 675465,
"title": "Fracture"
}, {
"listId": 65456475,
"id": 70111470,
"title": "Die Hard"
}, {
"listId": 65456475,
"id": 654356453,
"title": "Bad Boys"
}],
boxarts = [{
videoId: 65432445,
width: 130,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/TheChamber130.jpg"
}, {
videoId: 65432445,
width: 200,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/TheChamber200.jpg"
}, {
videoId: 675465,
width: 200,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/Fracture200.jpg"
}, {
videoId: 675465,
width: 120,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/Fracture120.jpg"
}, {
videoId: 675465,
width: 300,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/Fracture300.jpg"
}, {
videoId: 70111470,
width: 150,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/DieHard150.jpg"
}, {
videoId: 70111470,
width: 200,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/DieHard200.jpg"
}, {
videoId: 654356453,
width: 200,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/BadBoys200.jpg"
}, {
videoId: 654356453,
width: 140,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/BadBoys140.jpg"
}],
bookmarks = [{
videoId: 65432445,
time: 32432
}, {
videoId: 675465,
time: 3534543
}, {
videoId: 70111470,
time: 645243
}, {
videoId: 654356453,
time: 984934
}];
var videosByList = lists.map(function(list) {
return {
name: list.name,
videos: videos.filter(function(video) {
return video.listId == list.id;
}).map(function(video) {
return {
id: video.id,
title: video.title,
time: bookmarks.filter(function(bookmark) {
return bookmark.videoId == video.id;
}).pop().time,
boxart: boxarts.filter(function(boxart) {
return boxart.videoId == video.id;
}).sort(function(a, b) {
return a.url < b.url ? 1 : (a.url > b.url ? -1 : 0);
}).pop().url
};
})
};
});
document.querySelector('pre').appendChild(document.createTextNode(JSON.stringify(videosByList, null, 4)))
<pre></pre>
function combine () {
var Genres = [];
lists.forEach(function(genre) {
var currGenre = makeGenre(genre.name, []);
videos.filter(function(video){
if (video.listId === genre.id) {
return video;
}
}).forEach(function(video) {
var time = bookmarks.filter(function(mark){
if (video.id === mark.videoId) {
return mark.time;
}
})[0];
var art = boxarts.filter(function(art){
if (video.id === art.videoId) {
return art;
}
}).sort(function (a, b) { return a.width * a.height > b.width * b.height; })[0];
currGenre.videos.push(makeVideo(video.id, video.title, time, art));
});
Genres.push(currGenre);
});
return Genres;
}
function makeGenre (name) {
return {
name: name,
videos: []
};
}
function makeVideo (id, title, time, boxart) {
return {
id: id,
title: title,
time: time,
boxart: boxart
};
}
There is a "Show Answer" button in the exercise page linked by the OP. I guess the answer button was not working in the OP's chosen browser, so I have pasted the solution here, including extra background information for the exercise:
return lists.map(function(list) {
return {
name: list.name,
videos:
videos.
filter(function(video) {
return video.listId === list.id;
}).
concatMap(function(video) {
return Array.zip(
bookmarks.filter(function(bookmark) {
return bookmark.videoId === video.id;
}),
boxarts.filter(function(boxart) {
return boxart.videoId === video.id;
}).
reduce(function(acc,curr) {
return acc.width * acc.height < curr.width * curr.height ? acc : curr;
}),
function(bookmark, boxart) {
return { id: video.id, title: video.title, time: bookmark.time, boxart: boxart.url };
});
})
};
});
The exercises build on previous knowledge, which demonstrate the concatMap function (see Exercise 13 for the implementation), pasted here for convenience:
Array.prototype.concatMap = function(projectionFunctionThatReturnsArray) {
return this.
map(function(item) {
return projectionFunctionThatReturnsArray(item);
}).
// apply the concatAll function to flatten the two-dimensional array
concatAll();
};
concatAll is defined in Exercise 10, pasted here for convenience:
Array.prototype.concatAll = function() {
var results = [];
this.forEach(function(subArray) {
results.push.apply(results, subArray);
});
return results;
};
The exercise instructions also dictate: "There's just more one thing: you can't use indexers. In other words, this is illegal var itemInArray = movieLists[0];"
Edit
New information from OP. It seems like the OP would like to run the exercise without the context of the exercise page and see the answer produced to verify that it is correct. To do this you need some extra functions to be defined because the exercises implement slightly different versions to those supplied by default in JavaScript (i.e filter, map, reduce, concatMap, concatAll, zip). If you use the default JavaScript versions then results go missing as the OP described.
For your convenience, I have setup the required functions and the solution and logged the answer to the console in jsbin.com:
http://jsbin.com/tolupe/edit?js,console

I need to set a json object property in a object, then reference that property from another object in the same object [duplicate]

This question already has answers here:
Javascript Object Literal referring to another property in itself from another property
(3 answers)
Closed 9 years ago.
I have this issue, I want to be able to change the audio being used based on the browser. What I have is an object seen below, which has a "ext: { sound: '.mp3' }", at some point I will make some distinctions between browser then use something like "object.ext.sound = '.ogg'" to set the new sound type based off the browser being used. How do I reference that variable from within the object in for instance "StAd0"?
var object = {
ext: {
sound: '.mp3'
},
pref: {
acc: 1
},
StAd0: {
from: 25,
to: 180,
src: 'ar/55871'+ this.ext.sound,
du: 5228
},
Image_33: {
type: 15,
from: 4,
to: 48,
rp: 0,
rpa: 0,
mdi: 'Image_33c',
trin: 6,
trout: 6,
ef: {}
},
Image_33c: {
b: [171, 259, 850, 360],
ip: 'dr/7029_679_101.png',
dn: 'Image_33',
visible: 1,
accstr: 'Image ',
vb: [171, 259, 850, 360]
}
}
The way I have things now it keeps saying that "this.ext.sound" has a value of "undefined". I was thinking it has to do with scope but quite honestly I am stumped, I feel like I've tried every combination of dot notation to try to get the property but I am just not referencing the property correctly.
Any help is greatly appreciated, thanks in advance!
what your trying to do is not possible.
the object has to be initialized before its values can be referred to
you could use a function inside the object.
or change the initial val of StAd0.src to '' or 'ar/55871' then reset that value after you set the var object; to object.StAd0.src = 'ar/55871'+ object.ext.sound;
var object = {
ext: {
sound: '.mp3'
},
pref: {
acc: 1
},
StAd0: {
from: 25,
to: 180,
src: 'ar/55871',
du: 5228
},
Image_33: {
type: 15,
from: 4,
to: 48,
rp: 0,
rpa: 0,
mdi: 'Image_33c',
trin: 6,
trout: 6,
ef: {}
},
Image_33c: {
b: [171, 259, 850, 360],
ip: 'dr/7029_679_101.png',
dn: 'Image_33',
visible: 1,
accstr: 'Image ',
vb: [171, 259, 850, 360]
}
};
object.StAd0.src = 'ar/55871'+ object.ext.sound;
Then src must be a function.
var object = {
ext: {
sound: '.mp3'
},
pref: {
acc: 1
},
StAd0: {
from: 25,
to: 180,
src: function() {
return 'ar/55871'+ this.ext.sound;
},
du: 5228
},
Image_33: {
type: 15,
from: 4,
to: 48,
rp: 0,
rpa: 0,
mdi: 'Image_33c',
trin: 6,
trout: 6,
ef: {}
},
Image_33c: {
b: [171, 259, 850, 360],
ip: 'dr/7029_679_101.png',
dn: 'Image_33',
visible: 1,
accstr: 'Image ',
vb: [171, 259, 850, 360]
}
}
But you must get src like this,
object.stAd0.src();
EDIT:
There isn't anyway to do it without a function, because if you try that like this,
src: ar/55871+ this.ext.sound;
that will work only once at parse-time. Than it will have a static value inside.
If you can't change all src properties to function, you can get it like this as well.
var src = (typeof object.StAd0.src == "function")? object.StAd0.src() : object.StAd0.src;
So If src is defined as a function, it will call it else will take it like a property.
This should work, give it a try:
var object = {
ext: { sound: '.mp3' },
StAd0: { src: 'ar/55871'+ object.ext.sound }
}

Categories