I have a search-function, that searches for specific data within a huge Object.
Depending on how good a found entry matches, the finding gets "matchPoints" (or "Priority")
var findings = {};
for(var element in hugeObject){
var points = getMatchPoints( inputToSearchFor, hugeObject[element] );
if( points !== 0 ){ //It matched. At least a bit.
findings[ points ] = element;
}
}
Now I have all Elements, that somehow matched, within findings
.
The function which implements this has to return an Array of all these elements. The most relevant result on the first place.
I currently use this for sorting:
var priorities = Object.keys(findings); //Get the matchpoints of all findings
priorities.reverse(); //Sort with reverse order (highest priority / most matchpoints first)
var result = [];
for(var i=0; i<priorities.length; i++){
result.push( findings[i] );
}
return result;
I have several issues with this code:
- It is inefficient and probably very slow
- The
.reverse()
function sorts the priorities alphabetically, not numerically - If 2 findings have the same amount of matchpoints, the
findings
-entry gets overwritten. So the result isn't even valid.
How can I solve this problem in an efficient and elegant way?
Edit: I should mention, that although the object where I search is very big, I only get few valid results which matchPoints> 0. In fact, most of the time I'll get only 2-3 matches at all.
1 Answer 1
The .reverse() function sorts the priorities alphabetically, not numerically
This is because Object.keys
returns an array of strings.
If 2 findings have the same amount of matchpoints, the findings-entry gets overwritten. So the result isn't even valid.
Right, you want to push matches onto the array and sort it afterwards.
var findings = [];
for (var element in hugeObject) {
var points = getMatchPoints(inputToSearchFor, hugeObject[element]);
if (points) {
// It matched. At least a bit.
findings.push({ points: points, element: element });
}
}
findings.sort(function(a, b) { return b.points - a.points; });
Here I'm creating a new object with the number of match points stored in points
and the found object stored in element
, but you could store the point count directly in the found object if it makes more sense.
-
\$\begingroup\$ That's a much better approach than mine :) (Can you correct the findings-initialisation in your answer to
=[];
?) \$\endgroup\$maja– maja2014年06月20日 20:13:33 +00:00Commented Jun 20, 2014 at 20:13 -
\$\begingroup\$ Why is it neccessary to use
return a.points - b.points;
? Wouldn'treturn a.points > b.points;
also work? \$\endgroup\$maja– maja2014年06月20日 20:16:15 +00:00Commented Jun 20, 2014 at 20:16 -
\$\begingroup\$ Opps, fixed initialization.
Array.prototype.sort
is really looking for a positive or negative number (or zero) to be returned, so the boolean resulting froma.points > b.points
has to be converted to a number, and it would never be negative. I think it's more correct and efficient to do it this way. \$\endgroup\$Dagg– Dagg2014年06月20日 20:22:47 +00:00Commented Jun 20, 2014 at 20:22 -
\$\begingroup\$ I just noticed you are sorting in descending order, so you really want
b.points - a.points
\$\endgroup\$Dagg– Dagg2014年06月20日 20:26:29 +00:00Commented Jun 20, 2014 at 20:26 -
\$\begingroup\$ If I put the
points
-property directly into the element-field: Is there a convinient way of removing this property in the findings-array afterwards? If not, I would have to use a for loop. \$\endgroup\$maja– maja2014年06月20日 20:30:56 +00:00Commented Jun 20, 2014 at 20:30