user3590729
user3590729

Reputation:

Find max value in array of objects containing NaN values

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.

Upvotes: 1

Views: 565

Answers (5)

set0gut1
set0gut1

Reputation: 1672

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>

Upvotes: 0

baao
baao

Reputation: 73241

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);

Upvotes: 1

Jonas Wilms
Jonas Wilms

Reputation: 138267

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)));

Upvotes: 1

felixmosh
felixmosh

Reputation: 35503

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);

Upvotes: 0

CertainPerformance
CertainPerformance

Reputation: 370779

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);

Upvotes: 3

Related Questions