1

I have an array of objects and I want to get the max prevalence value.

I try this code:

// max of selected vaccine
var ex = [{"name": "a", "prevalence": "NaN"},
	{"name": "a", "prevalence": "5"},
	{"name": "b", "prevalence": "0"},
	{"name": "a", "prevalence": "NaN"},
	{"name": "c", "prevalence": "100"},
	{"name": "c", "prevalence": "20"},
	{"name": "a", "prevalence": "3"}];
console.log('ex:', ex);

var maxPrevalence = d3.max(ex, function(d) {
	if(!isNaN(d.prevalence)) {
		return d.prevalence;
	}
});
console.log('\nmaxPrevalence:', maxPrevalence);
<script src='https://d3js.org/d3.v5.js' charset='utf-8'></script>

But the result is 5 not 100.

I don't have to use a d3 function, even pure javascript is fine.

5 Answers 5

3

Your 'NaN's are strings, not actual NaNs, but regardless, you can reduce into Math.max while testing the prevalence :

var ex=[{"name":"a","prevalence":"NaN"},{"name":"a","prevalence":"5"},{"name":"b","prevalence":"0"},{"name":"a","prevalence":"NaN"},{"name":"c","prevalence":"100"},{"name":"c","prevalence":"20"},{"name":"a","prevalence":"3"}];
const max = Math.max(...ex.reduce(
  (accum, { prevalence }) =>
    isNaN(prevalence) ? accum : [...accum, prevalence],
  [])
);
console.log(max);

Sign up to request clarification or add additional context in comments.

3 Comments

That would look nicer, but it would also require iterating over the array twice when it could be done at once with reduce. (in the rare case that efficiency matters)
I disagree. Recreating an array at every iteration is definetly slower than chained native methods, that get optimized by most browsers
A single map is enough, no need for two loops, filter @JonasW. Look at my answer
1

Actually "5" is bigger than "100" as they are compared as strings. You need to make sure that they are compared as numbers:

return +d.prevalence;

Or you take a slightly easuer approach:

  const maxPrevalence = Math.max(...ex.map(d => +d.prevalence).filter(p => !isNaN(p)));

1 Comment

The second returns NaN
1

You can use Math.max() on the mapped prevalence values:

var ex = [{"name": "a", "prevalence": "NaN"},  {"name": "a", "prevalence": "5"},  {"name": "b", "prevalence": "0"},  {"name": "a", "prevalence": "NaN"},  {"name": "c", "prevalence": "100"},  {"name": "c", "prevalence": "20"},  {"name": "a", "prevalence": "3"}];
let max = Math.max(...ex.map(e => isNaN(e.prevalence) ? Number.MIN_SAFE_INTEGER : e.prevalence));
console.log(max);

Comments

0

You can use Array.reduce & parseInt in order to iterate the array, and search for the max value; The usage of parseInt is required because prevalence is a string.

const ex = [{
    "name": "a",
    "prevalence": "NaN"
  },
  {
    "name": "a",
    "prevalence": "5"
  },
  {
    "name": "b",
    "prevalence": "0"
  },
  {
    "name": "a",
    "prevalence": "NaN"
  },
  {
    "name": "c",
    "prevalence": "100"
  },
  {
    "name": "c",
    "prevalence": "20"
  },
  {
    "name": "a",
    "prevalence": "3"
  }
];

const result = ex.reduce((max, current) => {
  const prevalence = parseInt(current.prevalence) || 0;
  return max.prevalence > prevalence ? max : current;
}, {
  prevalence: '0'
});

console.log(result);

Comments

0

With d3.js, this code works. Number("100") is number 100, and Number('NaN') is number NaN.

// max of selected vaccine
var ex = [{"name": "a", "prevalence": "NaN"}, {"name": "a", "prevalence": "5"}, {"name": "b", "prevalence": "0"}, {"name": "a", "prevalence": "NaN"}, {"name": "c", "prevalence": "100"}, {"name": "c", "prevalence": "20"}, {"name": "a", "prevalence": "3"}];

var maxPrevalence = d3.max(ex, function(d) { return Number(d.prevalence) });
console.log('\nmaxPrevalence:', maxPrevalence);
<script src='https://d3js.org/d3.v5.js' charset='utf-8'></script>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.