I have a json array of about 30 objects. Here's a sample object from the array:
{
"id": 0,
"name": "Valle",
"activities": "night-life",
"food": "fancy-food",
"sport" : "baseball",
"geoProfile": "artsy",
"priority": 2
}
I am building out another object on a page based on user input. The user will choose between radio buttons and after they have made their choices, I will have an object such as:
{geoProfile: "artsy", activities: "nature", food: "fancy-food", sport: "cricket"}
I am using jQuery's $.each()
method to go through each object as follows:
$.each(self.data(), function (i, s) {
if (s.geoProfile == self.prefLocation() &&
s.activities == self.prefActivity() &&
s.food == self.prefFood() &&
s.sport == self.prefSport()) {
optionMatched = s;
return false;
}
});
This will return an object that has all four matches, but how can I return the json object that has the most matches to the user-built object? If two match, I want to then look at the "priority" property and return the one with the lowest priority.
You could use Array#map
and build a new array with the sum of the matched properties.
Later you can sort with map and use the result for sorting and get the first element.
var data = [/* your data here */],
search = { geoProfile: "artsy", activities: "nature", food: "fancy-food", sport: "cricket" },
result = data.map(function (a, i) {
return {
count: Object.keys(search).reduce(function (r, k) { return r + +(a[k] === search[k]); }, 0),
priority: a.priority,
index: i
}
});
result.sort(function (a, b) {
return b.count - a.count || a.priority - b.priority;
});
A single loop solution
var data = [/* your data here */],
search = { geoProfile: "artsy", activities: "nature", food: "fancy-food", sport: "cricket" },
result = data.reduce(function (r, a, i) {
document.write('<pre>' + JSON.stringify(r, 0, 4) + '</pre><hr>');
var o = {
count: Object.keys(search).reduce(function (q, k) { return q + +(a[k] === search[k]); }, 0),
priority: a.priority,
index: i
};
if (!i || o.count > r[0].count || o.count === r[0].count && o.priority < r[0].priority) {
return [o];
}
o.count === r[0].count && o.priority === r[0].priority && r.push(o);
return r;
}, []);
Just track the number of matches and update your selected one based on if it has more matches.
var numOfMatches = 0;
$.each(self.data(), function(i, s) {
var matchingProperties = 0;
if (s.geoProfile == self.prefLocation()) {
matchingProperties++;
}
if (s.activities == self.prefActivity()) {
matchingProperties++;
}
if (s.food == self.prefFood()) {
matchingProperties++;
}
if (s.sport == self.prefSport()) {
matchingProperties++;
}
if (matchingProperties === 0 || matchingProperties < numOfMatches) {
return;
}
if (!optionMatched // Grab the first match
|| matchingProperties > numOfMatches // or if more properties match
|| s.priority < optionMatched.priority) { // or the one with a lower priority
optionMatched = s;
numOfMatches = matchingProperties;
}
});
Or you could simplify the initial counting using filter
:
var numOfMatches = 0;
$.each(self.data(), function(i, s) {
var matchingProperties = [
s.geoProfile == self.prefLocation(),
s.activities == self.prefActivity(),
s.food == self.prefFood(),
s.sport == self.prefSport()
].filter(function(val) { return val; }).length;
if (matchingProperties === 0 || matchingProperties < numOfMatches) {
return;
}
if (!optionMatched // Grab the first match
|| matchingProperties > numOfMatches // or if more properties match
|| s.priority < optionMatched.priority) { // or the one with a lower priority
optionMatched = s;
numOfMatches = matchingProperties;
}
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.