-1

I have a large array, named data, of string values from an external source, where each is supposed to represent an integer.

When I leave it to Javascript's automatic type conversion, there were no Javascript errors when I ran some arithmetic calculations on the whole array.

However, an operation like if (data[i] > data[i-1]) count++; gives the wrong result for some of the array entries. I don't know which.

When I added the following manual conversion step, then computation on the array of numbers gave the expected result:

data.forEach((n, i) => {
  data[i] = Number(n);
});

In other words, the same computation on data gives different outcomes when the above step is included or not.

As the array is large, it is not practical for me to comb through the data to pick out the offending ones. I want to find out where the problem is. I modified the forEach loop to:

data.forEach((n, i) => {
  if (data[i] != Number(n)) console.log("!!!", i, n);
  data[i] = Number(n);
});

but nothing was printed out.

What is a method to find out which values of the array are problematic?

data is like: [ "123", "234", "456", "789", .... ].


If you want to know how I knew there was a problem, a colleague used Python on the same set of data and produced a different result. That led to an investigation.

mplungjan
  • 169,008
  • 28
  • 173
  • 236
Old Geezer
  • 14,854
  • 31
  • 111
  • 198
  • 2
    Here is a minimal example: `"2" > "10"` -> true – Salman A Dec 03 '21 at 08:17
  • 1
    Do you have an example of a "problematic" number? – Dane Brouwer Dec 03 '21 at 08:19
  • 3
    @OldGeezer They're *all* problematic, since they're strings not numbers. If you compare strings, that happens alphabetically not by value. It only works by luck if both strings have the same number of digits. – Bergi Dec 03 '21 at 08:19
  • 2
    Your data contains *strings*, not numbers. Whether or not there is a conversion happening depends on the operation you do. Relational operators like `>` will *not* convert if both operands are the same type, so two strings will be compared as strings. But if one is a number, another a string, the string will be converted to a number for the comparison. – VLAZ Dec 03 '21 at 08:21
  • 1
    @Bergi You hit it on the nail! So there was no type conversion. The errors happen when the strings transited from, say, 3 digits to 4 digts. – Old Geezer Dec 03 '21 at 08:21
  • `data[i] != Number(n)` should be `data[i] !== Number(n)`. Note the double `=` – Weedoze Dec 03 '21 at 08:23
  • @Weedoze If that was the desired behavior, you could just do `typeof data[i] == 'number'` straight away – Bergi Dec 03 '21 at 08:25
  • After finally grasping the problem, the solution is simple using the unary plus operator `if (i>0 && +data[i] > +data[i-1]) count++;` – mplungjan Dec 03 '21 at 08:44

1 Answers1

-1

If you're expecting valid integers in the strings, try this method to discover which ones might be problems:

const data = ["123", "234", "456", "789", "", "2,234", "2.02", "1e3", "n0", "invalid", "2", "10"];

for (const [index, str] of data.entries()) {
  if (parseInt(str, 10) !== Number(str)) console.log(index, str);
}
jsejcksn
  • 27,667
  • 4
  • 38
  • 62
  • Try that on `["2", "10"]` – Salman A Dec 03 '21 at 08:21
  • @SalmanA Appended to data array – jsejcksn Dec 03 '21 at 08:23
  • 1
    My point is that your function will pass both numbers as valid. But when you compare them using < or > the problem will still be there. – Salman A Dec 03 '21 at 08:24
  • 1
    What problem? The example demonstrates a method for determining which string values cannot be unambiguously parsed as base-10 integers. – jsejcksn Dec 03 '21 at 08:26
  • @mplungjan I disagree that `1e3` is an unambiguously valid integer. In many domains, yes, but definitely not all – jsejcksn Dec 03 '21 at 08:32
  • Look at OP's comment. The problem has already been solved. OP does not have invalid numbers in data. He clearly mentions that problem happens when for example a 2 digit number is compared with a 3 digit one e.g. "20" > "123" is returning true. – Salman A Dec 03 '21 at 08:36