I'm trying to create an advance search function to use on a multi-dimensional array of product objects. On the form, the user will have the option of narrowing down product results based on data in several different attributes (e.g. "'price' < 20 && 'country' == 'France'", "region == 'New York' && 'vintage' == '2016' && 'qty > 20"). The data, within variable data
is formatted as follows:
0:
name: "Kedem Cream Red Concord"
appellation: "New York"
country: "United States"
price: "10.99"
primarygrape: "Concord"
qty: "1"
region: "New York"
regprice: "10.99"
sku: "230"
vintage: "NV"
1:
name: "Kendall Jackson Vintner's Chardonnay"
appellation: ""
country: "United States"
price: "14.99"
primarygrape: "Chardonnay"
qty: "35"
region: "California"
regprice: "18.99"
sku: "345"
vintage: "2016"
... continuing on over 10,000 product records
I figured I could create a string based on the user form input fairly easily that sums up what they're searching for. However, I need a safe way to evaluate that string within my function that returns the filtered results in resultsArray
I was able to get it to work with the eval()
function, but I know that's not safe or efficient. I also tried fooling around with putting the conditions into an array and trying to incorporate that into the for loop, but I couldn't figure out how to make it work. The tricky part is, the conditions could be any number of things involving the following product attributes: appellation, country, price, primarygrape, qty, region, vintage. And different attributes use different operators (e.g. country, region, and others use '==' while qty and price use '>' or '<').
This code works, but uses the taboo eval()
function:
var conditional = "data[i].price < 20 && data[i].country == 'France' && data[i].vintage == '2016'";
var resultArray = [];
console.log(data.length);
for (var i = 0; i < data.length; i++)
{
if (eval(conditional))
{
resultArray.push(data[i]);
}
}
}
This doesn't work, as it results in a Uncaught ReferenceError: data is not defined
error:
var conditional = "return data[i].price < 20 && data[i].country == 'France' && data[i].vintage == '2016'";
var resultArray = [];
console.log(data.length);
for (var i = 0; i < data.length; i++)
{
if (new Function(conditional)())
{
resultArray.push(data[i]);
}
}
}
Any idea how to dynamically create that if conditional statement so that it recognizes the data
variable? Or, is there a better solution?
Javascript Arrays have a function called filter
which can be used to do things like you want to achieve.
For example you have an array with numbers:
var arr = [1,3,6,2,6]
And your plan is to filter all even numbers.You can use array.filter()
.
you need to pass an anonymous function into it. This function gets called once every entry in which you have access to the current element.
You need to return a boolean in this function - true
means
that the element will be in the new, filtered array
Now the completed example to filter all even numbers:
arr.filter(function(element) {return element%2 == 0})
I hope that's enough for you to continue. :-) In the next snippet I made a small example with your data array
var your_data_array = [
{
name: "Kendall Jackson Vintner's Chardonnay",
appellation: "",
country: "United States",
price: "14.99",
primarygrape: "Chardonnay",
qty: "35",
region: "California",
regprice: "18.99",
sku: "345",
vintage: "2016" },
{
name: "Kendall Jackson Vintner's Chardonnay",
appellation: "",
country: "United States",
price: "14.99",
primarygrape: "Chardonnay",
qty: "35",
region: "California",
regprice: "18.99",
sku: "345",
vintage: "2016" },
{
name: "Kendall Jackson Vintner's Chardonnay",
appellation: "",
country: "United States",
price: "14.99",
primarygrape: "Chardonnay",
qty: "35",
region: "California",
regprice: "18.99",
sku: "345",
vintage: "2016" }
]
var filtered_array = your_data_array.filter(function(dataElement) {
return dataElement.country == "United States";
})
console.log(filtered_array)