Skip to main content
Participant
December 16, 2021
Answered

2D array search

  • December 16, 2021
  • 2 replies
  • 908 views

I am trying to create a 2D array to search a value based on width and projection, i got stuck at this.

 

var width = this.getField("Width").value;
var projection = this.getField("projection").value;
const table = [

{ width: 2000, projections: [{ size: 200, price: 499}, { size: 400, price: 1499}]},
{ width: 3000, projections: [{ size: 200, price: 999}, { size: 400, price: 1999}]},
];

// return the relevant row based on the awning width
const projections = table.filter(function(item) {
return item.width == (Math.ceil(width/1000)*1000);
}).map(function(width) { return width.projections });

// take this result and filter by projection size
const price = projections[0].filter(function(projection) {
return projection.size == projection;
})[0];

event.value = price.price;

This topic has been closed for replies.
Correct answer Thom Parker

There are a few issues with this code.

First of couse is the formatting. Please do not post code that is all run together. It's impossible to read. Use the "Code Sample Block" tool to give it proper formatting. 

 

Next, there's no good reason to make the variables constants. Because this code is in a calculation script, it already has block scope. And if the data table was moved to a document script, it would have document scope. Although this is not an error, overuse of constants gets in the way of re-running the code for debug purposes. 

Next, you've reused the same variable names (this is the source of your error),

and you've used confusing names. When passing predicate functions, it's best to use a consistent naming convention for the predicate variable. It reduces confusion and conflicts. 

It's also a good idea to use type prefixes on your variable to reduce confusion and conflicts. 

Also, the code does not handle the No Match case, which will cause the 2nd to last line to throw an exception. 

 

Here's a simple re-write that takes care of these issues:

Note that since the "some" function is used to iterate through the table that it could also be used to detect matched result. However, the initial value of 0 for the price does the same thing by default, just as long as none of the prices are 0.

 

var nWidth = (Math.ceil(this.getField("Width").value/1000)*1000);
var nProjection = this.getField("projection").value;
var table = [
   { width: 2000, projections: [{ size: 200, price: 499}, { size: 400, price: 1499}]},
   { width: 3000, projections: [{ size: 200, price: 999}, { size: 400, price: 1999}]},
];

// return the relevant row based on the awning width
var nPrice = 0;
table.some(function(oItem){ return (oItem.width == nWidth) && oItem.projections.some(function(oProj){return (oProj.size == nProjection) && (nPrice = oProj.price);});})

event.value = nPrice;

 

 

2 replies

Participant
December 20, 2021

Hi Thom.

 

You star! i did need to change 

var nPrice = 0;

to 

var nPrice = table.some

to work.

Else the outp put was just 0, or what evert figure was typed after nPrice.

 

 

Many thanks 

Thom Parker
Community Expert
Community Expert
December 20, 2021

What do you mean you set "var nPrice = table.some"?   That is not a good idea. It sets up a conflict. "nPrice" is set inside the predicate function.  It only takes on a value of 0 if there is no match, which is the point.

By setting to the result of "table.some" it is overwritten with a true/false value.  

 

 

 

Thom Parker - Software Developer at PDFScriptingUse the Acrobat JavaScript Reference early and often
Participant
December 20, 2021

Hi Thom

 

Yes, sorry you are correct, i adjusted back to 0.

 

My next problem is rounding the values up to the next array value.

If i use n/250)*250 and the array number match 250 increments, then the code works, however i need the whole number of the 250 to jump to the next figure.

 

so between 2000 and 4249 is 2, 4250 to 5249 is 3 etc

If i change the array 4250 to be 2249, it than displays 0.

 

Is the celing interger set from 0? i.e if you set 250, all number must be divisable by 250?

Any ideas? 

 

many thanks

Rob

 

Thom Parker
Community Expert
Thom ParkerCommunity ExpertCorrect answer
Community Expert
December 19, 2021

There are a few issues with this code.

First of couse is the formatting. Please do not post code that is all run together. It's impossible to read. Use the "Code Sample Block" tool to give it proper formatting. 

 

Next, there's no good reason to make the variables constants. Because this code is in a calculation script, it already has block scope. And if the data table was moved to a document script, it would have document scope. Although this is not an error, overuse of constants gets in the way of re-running the code for debug purposes. 

Next, you've reused the same variable names (this is the source of your error),

and you've used confusing names. When passing predicate functions, it's best to use a consistent naming convention for the predicate variable. It reduces confusion and conflicts. 

It's also a good idea to use type prefixes on your variable to reduce confusion and conflicts. 

Also, the code does not handle the No Match case, which will cause the 2nd to last line to throw an exception. 

 

Here's a simple re-write that takes care of these issues:

Note that since the "some" function is used to iterate through the table that it could also be used to detect matched result. However, the initial value of 0 for the price does the same thing by default, just as long as none of the prices are 0.

 

var nWidth = (Math.ceil(this.getField("Width").value/1000)*1000);
var nProjection = this.getField("projection").value;
var table = [
   { width: 2000, projections: [{ size: 200, price: 499}, { size: 400, price: 1499}]},
   { width: 3000, projections: [{ size: 200, price: 999}, { size: 400, price: 1999}]},
];

// return the relevant row based on the awning width
var nPrice = 0;
table.some(function(oItem){ return (oItem.width == nWidth) && oItem.projections.some(function(oProj){return (oProj.size == nProjection) && (nPrice = oProj.price);});})

event.value = nPrice;

 

 

Thom Parker - Software Developer at PDFScriptingUse the Acrobat JavaScript Reference early and often