Why does passing in a number as a string into an array cause the wrong result?












0















I have built a function that allows you to pass through an array and it successfully returns the second highest and second lowest numbers. However, I'm new to error handling and don't understand why this fails:



getNos([5,"5",8]);


It works correctly when passing in getNos([5,5,8]); or passing arrays like getNos(["5",8]);.



Can someone explain what's happening here and how to fix it? Thanks for any help here - the function code is below:



function getNos(arr){

if (!Array.isArray(arr) || arr.length == 0 || arr.length == 1 || (arr.every(c => !isNaN(c)) == false)) {
throw 'Invalid Input';
} else {

var result;
var uniqueVals = Array.from(new Set(arr));
var highest = highestVal(arr);
var lowest = lowestVal(arr);

if (uniqueVals.length == 1) {
result = arr[0] + " " + arr[0];
} else if (arr.length == 2 || uniqueVals.length == 2) {
result = highest + " " + lowest;
} else {
arr = arr.filter(item => ((item !== highest) && (item !== lowest)));
var secondHighest = highestVal(arr);
var secondLowest = lowestVal(arr);

if (arr.length == 1) {
arr = arr.slice(arr.indexOf(secondHighest));
result = highestVal(arr);
} else {
result = secondLowest + " " + secondHighest;
}
}
return result;
}

function highestVal(a) { return a.reduce((a, b) => a > b ? a : b ) };
function lowestVal(a) { return a.reduce((a, b) => a < b ? a : b ) };
}









share|improve this question


















  • 1





    What is the "wrong result" ?

    – epascarello
    Nov 19 '18 at 15:44






  • 1





    It works correctly when passing in [...] or passing arrays like [...]. So when does it not work?

    – MrUpsidown
    Nov 19 '18 at 15:45
















0















I have built a function that allows you to pass through an array and it successfully returns the second highest and second lowest numbers. However, I'm new to error handling and don't understand why this fails:



getNos([5,"5",8]);


It works correctly when passing in getNos([5,5,8]); or passing arrays like getNos(["5",8]);.



Can someone explain what's happening here and how to fix it? Thanks for any help here - the function code is below:



function getNos(arr){

if (!Array.isArray(arr) || arr.length == 0 || arr.length == 1 || (arr.every(c => !isNaN(c)) == false)) {
throw 'Invalid Input';
} else {

var result;
var uniqueVals = Array.from(new Set(arr));
var highest = highestVal(arr);
var lowest = lowestVal(arr);

if (uniqueVals.length == 1) {
result = arr[0] + " " + arr[0];
} else if (arr.length == 2 || uniqueVals.length == 2) {
result = highest + " " + lowest;
} else {
arr = arr.filter(item => ((item !== highest) && (item !== lowest)));
var secondHighest = highestVal(arr);
var secondLowest = lowestVal(arr);

if (arr.length == 1) {
arr = arr.slice(arr.indexOf(secondHighest));
result = highestVal(arr);
} else {
result = secondLowest + " " + secondHighest;
}
}
return result;
}

function highestVal(a) { return a.reduce((a, b) => a > b ? a : b ) };
function lowestVal(a) { return a.reduce((a, b) => a < b ? a : b ) };
}









share|improve this question


















  • 1





    What is the "wrong result" ?

    – epascarello
    Nov 19 '18 at 15:44






  • 1





    It works correctly when passing in [...] or passing arrays like [...]. So when does it not work?

    – MrUpsidown
    Nov 19 '18 at 15:45














0












0








0








I have built a function that allows you to pass through an array and it successfully returns the second highest and second lowest numbers. However, I'm new to error handling and don't understand why this fails:



getNos([5,"5",8]);


It works correctly when passing in getNos([5,5,8]); or passing arrays like getNos(["5",8]);.



Can someone explain what's happening here and how to fix it? Thanks for any help here - the function code is below:



function getNos(arr){

if (!Array.isArray(arr) || arr.length == 0 || arr.length == 1 || (arr.every(c => !isNaN(c)) == false)) {
throw 'Invalid Input';
} else {

var result;
var uniqueVals = Array.from(new Set(arr));
var highest = highestVal(arr);
var lowest = lowestVal(arr);

if (uniqueVals.length == 1) {
result = arr[0] + " " + arr[0];
} else if (arr.length == 2 || uniqueVals.length == 2) {
result = highest + " " + lowest;
} else {
arr = arr.filter(item => ((item !== highest) && (item !== lowest)));
var secondHighest = highestVal(arr);
var secondLowest = lowestVal(arr);

if (arr.length == 1) {
arr = arr.slice(arr.indexOf(secondHighest));
result = highestVal(arr);
} else {
result = secondLowest + " " + secondHighest;
}
}
return result;
}

function highestVal(a) { return a.reduce((a, b) => a > b ? a : b ) };
function lowestVal(a) { return a.reduce((a, b) => a < b ? a : b ) };
}









share|improve this question














I have built a function that allows you to pass through an array and it successfully returns the second highest and second lowest numbers. However, I'm new to error handling and don't understand why this fails:



getNos([5,"5",8]);


It works correctly when passing in getNos([5,5,8]); or passing arrays like getNos(["5",8]);.



Can someone explain what's happening here and how to fix it? Thanks for any help here - the function code is below:



function getNos(arr){

if (!Array.isArray(arr) || arr.length == 0 || arr.length == 1 || (arr.every(c => !isNaN(c)) == false)) {
throw 'Invalid Input';
} else {

var result;
var uniqueVals = Array.from(new Set(arr));
var highest = highestVal(arr);
var lowest = lowestVal(arr);

if (uniqueVals.length == 1) {
result = arr[0] + " " + arr[0];
} else if (arr.length == 2 || uniqueVals.length == 2) {
result = highest + " " + lowest;
} else {
arr = arr.filter(item => ((item !== highest) && (item !== lowest)));
var secondHighest = highestVal(arr);
var secondLowest = lowestVal(arr);

if (arr.length == 1) {
arr = arr.slice(arr.indexOf(secondHighest));
result = highestVal(arr);
} else {
result = secondLowest + " " + secondHighest;
}
}
return result;
}

function highestVal(a) { return a.reduce((a, b) => a > b ? a : b ) };
function lowestVal(a) { return a.reduce((a, b) => a < b ? a : b ) };
}






javascript






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 19 '18 at 15:36









user8758206user8758206

453110




453110








  • 1





    What is the "wrong result" ?

    – epascarello
    Nov 19 '18 at 15:44






  • 1





    It works correctly when passing in [...] or passing arrays like [...]. So when does it not work?

    – MrUpsidown
    Nov 19 '18 at 15:45














  • 1





    What is the "wrong result" ?

    – epascarello
    Nov 19 '18 at 15:44






  • 1





    It works correctly when passing in [...] or passing arrays like [...]. So when does it not work?

    – MrUpsidown
    Nov 19 '18 at 15:45








1




1





What is the "wrong result" ?

– epascarello
Nov 19 '18 at 15:44





What is the "wrong result" ?

– epascarello
Nov 19 '18 at 15:44




1




1





It works correctly when passing in [...] or passing arrays like [...]. So when does it not work?

– MrUpsidown
Nov 19 '18 at 15:45





It works correctly when passing in [...] or passing arrays like [...]. So when does it not work?

– MrUpsidown
Nov 19 '18 at 15:45












3 Answers
3






active

oldest

votes


















3














Follow carefully the logic var uniqueVals = Array.from(new Set(arr)). What will this line return when you have arrays such as [5,"5",8] vs [5,5,8] vs ["5", 8]?



A Set stores unique value of a type. "5" is of type string whereas 5 is of type number. The highestVal and lowestVal functions can compare "5" and 8, no problem, but since an array could include either a string or number for either 5 or 8 as well, then you will get funny values being returned.



To fix this, before passing arr to the Set, you need to convert all values to a single type, preferably number.



let numberArr = arr.map(el=>+el) is one way of doing that, but you may want better data validation than that.






share|improve this answer
























  • ahh I see... the logic is always right. thanks...

    – user8758206
    Nov 19 '18 at 16:07



















1














Simple fix would be map the values to numbers before creating the set to avoid having the same numeric values as both string and number in the set



Change



var uniqueVals = Array.from(new Set(arr));


To



var uniqueVals = Array.from(new Set(arr.map(Number)));





share|improve this answer


























  • Why? Would you care explaining what your code does and how it will fix OP's question?

    – MrUpsidown
    Nov 19 '18 at 15:48











  • Because String "5" and number 5 would create separate values in set

    – charlietfl
    Nov 19 '18 at 15:49











  • I see. What will happen then if you pass getNos([5,"4",8])? I don't think that's what OP was asking for...

    – MrUpsidown
    Nov 19 '18 at 15:52






  • 1





    What's wrong with that case? uniqueVals would be [5,4,8]. All the values have to pass OP's isNan test

    – charlietfl
    Nov 19 '18 at 15:54













  • didn't realise it would be such a simple fix, thank you

    – user8758206
    Nov 19 '18 at 16:09



















1














The function does not fail in the sense that it throws an error. For these types of questions please add an example of "expected results".



When you compare strings and numbers in JavaScript, you are relying on implicit coercion to take care of the comparison. In this case it won't throw and error and break anything, it is fine as JavaScript will convert your string to a number and compare (unless its a strict equality === which checks type as well).



Should the result be based off what was passed in? Or after the input has been filtered for numbers only. Or if the input can be converted to valid numbers?



In the case of filter for valid numbers. Filter the input as follows...



  arr = arr.filter(data => typeof data === 'number')


In the case of converting values to a number and removing those that cannot be converted...



  arr = arr.reduce(((acc, el) => {
const num = Number(el);
if (!Number.isNaN(num)) acc.push(num);
return acc;
}), );





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53377992%2fwhy-does-passing-in-a-number-as-a-string-into-an-array-cause-the-wrong-result%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    3














    Follow carefully the logic var uniqueVals = Array.from(new Set(arr)). What will this line return when you have arrays such as [5,"5",8] vs [5,5,8] vs ["5", 8]?



    A Set stores unique value of a type. "5" is of type string whereas 5 is of type number. The highestVal and lowestVal functions can compare "5" and 8, no problem, but since an array could include either a string or number for either 5 or 8 as well, then you will get funny values being returned.



    To fix this, before passing arr to the Set, you need to convert all values to a single type, preferably number.



    let numberArr = arr.map(el=>+el) is one way of doing that, but you may want better data validation than that.






    share|improve this answer
























    • ahh I see... the logic is always right. thanks...

      – user8758206
      Nov 19 '18 at 16:07
















    3














    Follow carefully the logic var uniqueVals = Array.from(new Set(arr)). What will this line return when you have arrays such as [5,"5",8] vs [5,5,8] vs ["5", 8]?



    A Set stores unique value of a type. "5" is of type string whereas 5 is of type number. The highestVal and lowestVal functions can compare "5" and 8, no problem, but since an array could include either a string or number for either 5 or 8 as well, then you will get funny values being returned.



    To fix this, before passing arr to the Set, you need to convert all values to a single type, preferably number.



    let numberArr = arr.map(el=>+el) is one way of doing that, but you may want better data validation than that.






    share|improve this answer
























    • ahh I see... the logic is always right. thanks...

      – user8758206
      Nov 19 '18 at 16:07














    3












    3








    3







    Follow carefully the logic var uniqueVals = Array.from(new Set(arr)). What will this line return when you have arrays such as [5,"5",8] vs [5,5,8] vs ["5", 8]?



    A Set stores unique value of a type. "5" is of type string whereas 5 is of type number. The highestVal and lowestVal functions can compare "5" and 8, no problem, but since an array could include either a string or number for either 5 or 8 as well, then you will get funny values being returned.



    To fix this, before passing arr to the Set, you need to convert all values to a single type, preferably number.



    let numberArr = arr.map(el=>+el) is one way of doing that, but you may want better data validation than that.






    share|improve this answer













    Follow carefully the logic var uniqueVals = Array.from(new Set(arr)). What will this line return when you have arrays such as [5,"5",8] vs [5,5,8] vs ["5", 8]?



    A Set stores unique value of a type. "5" is of type string whereas 5 is of type number. The highestVal and lowestVal functions can compare "5" and 8, no problem, but since an array could include either a string or number for either 5 or 8 as well, then you will get funny values being returned.



    To fix this, before passing arr to the Set, you need to convert all values to a single type, preferably number.



    let numberArr = arr.map(el=>+el) is one way of doing that, but you may want better data validation than that.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 19 '18 at 15:46









    wlhwlh

    1,8261823




    1,8261823













    • ahh I see... the logic is always right. thanks...

      – user8758206
      Nov 19 '18 at 16:07



















    • ahh I see... the logic is always right. thanks...

      – user8758206
      Nov 19 '18 at 16:07

















    ahh I see... the logic is always right. thanks...

    – user8758206
    Nov 19 '18 at 16:07





    ahh I see... the logic is always right. thanks...

    – user8758206
    Nov 19 '18 at 16:07













    1














    Simple fix would be map the values to numbers before creating the set to avoid having the same numeric values as both string and number in the set



    Change



    var uniqueVals = Array.from(new Set(arr));


    To



    var uniqueVals = Array.from(new Set(arr.map(Number)));





    share|improve this answer


























    • Why? Would you care explaining what your code does and how it will fix OP's question?

      – MrUpsidown
      Nov 19 '18 at 15:48











    • Because String "5" and number 5 would create separate values in set

      – charlietfl
      Nov 19 '18 at 15:49











    • I see. What will happen then if you pass getNos([5,"4",8])? I don't think that's what OP was asking for...

      – MrUpsidown
      Nov 19 '18 at 15:52






    • 1





      What's wrong with that case? uniqueVals would be [5,4,8]. All the values have to pass OP's isNan test

      – charlietfl
      Nov 19 '18 at 15:54













    • didn't realise it would be such a simple fix, thank you

      – user8758206
      Nov 19 '18 at 16:09
















    1














    Simple fix would be map the values to numbers before creating the set to avoid having the same numeric values as both string and number in the set



    Change



    var uniqueVals = Array.from(new Set(arr));


    To



    var uniqueVals = Array.from(new Set(arr.map(Number)));





    share|improve this answer


























    • Why? Would you care explaining what your code does and how it will fix OP's question?

      – MrUpsidown
      Nov 19 '18 at 15:48











    • Because String "5" and number 5 would create separate values in set

      – charlietfl
      Nov 19 '18 at 15:49











    • I see. What will happen then if you pass getNos([5,"4",8])? I don't think that's what OP was asking for...

      – MrUpsidown
      Nov 19 '18 at 15:52






    • 1





      What's wrong with that case? uniqueVals would be [5,4,8]. All the values have to pass OP's isNan test

      – charlietfl
      Nov 19 '18 at 15:54













    • didn't realise it would be such a simple fix, thank you

      – user8758206
      Nov 19 '18 at 16:09














    1












    1








    1







    Simple fix would be map the values to numbers before creating the set to avoid having the same numeric values as both string and number in the set



    Change



    var uniqueVals = Array.from(new Set(arr));


    To



    var uniqueVals = Array.from(new Set(arr.map(Number)));





    share|improve this answer















    Simple fix would be map the values to numbers before creating the set to avoid having the same numeric values as both string and number in the set



    Change



    var uniqueVals = Array.from(new Set(arr));


    To



    var uniqueVals = Array.from(new Set(arr.map(Number)));






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 19 '18 at 15:51

























    answered Nov 19 '18 at 15:45









    charlietflcharlietfl

    139k1387120




    139k1387120













    • Why? Would you care explaining what your code does and how it will fix OP's question?

      – MrUpsidown
      Nov 19 '18 at 15:48











    • Because String "5" and number 5 would create separate values in set

      – charlietfl
      Nov 19 '18 at 15:49











    • I see. What will happen then if you pass getNos([5,"4",8])? I don't think that's what OP was asking for...

      – MrUpsidown
      Nov 19 '18 at 15:52






    • 1





      What's wrong with that case? uniqueVals would be [5,4,8]. All the values have to pass OP's isNan test

      – charlietfl
      Nov 19 '18 at 15:54













    • didn't realise it would be such a simple fix, thank you

      – user8758206
      Nov 19 '18 at 16:09



















    • Why? Would you care explaining what your code does and how it will fix OP's question?

      – MrUpsidown
      Nov 19 '18 at 15:48











    • Because String "5" and number 5 would create separate values in set

      – charlietfl
      Nov 19 '18 at 15:49











    • I see. What will happen then if you pass getNos([5,"4",8])? I don't think that's what OP was asking for...

      – MrUpsidown
      Nov 19 '18 at 15:52






    • 1





      What's wrong with that case? uniqueVals would be [5,4,8]. All the values have to pass OP's isNan test

      – charlietfl
      Nov 19 '18 at 15:54













    • didn't realise it would be such a simple fix, thank you

      – user8758206
      Nov 19 '18 at 16:09

















    Why? Would you care explaining what your code does and how it will fix OP's question?

    – MrUpsidown
    Nov 19 '18 at 15:48





    Why? Would you care explaining what your code does and how it will fix OP's question?

    – MrUpsidown
    Nov 19 '18 at 15:48













    Because String "5" and number 5 would create separate values in set

    – charlietfl
    Nov 19 '18 at 15:49





    Because String "5" and number 5 would create separate values in set

    – charlietfl
    Nov 19 '18 at 15:49













    I see. What will happen then if you pass getNos([5,"4",8])? I don't think that's what OP was asking for...

    – MrUpsidown
    Nov 19 '18 at 15:52





    I see. What will happen then if you pass getNos([5,"4",8])? I don't think that's what OP was asking for...

    – MrUpsidown
    Nov 19 '18 at 15:52




    1




    1





    What's wrong with that case? uniqueVals would be [5,4,8]. All the values have to pass OP's isNan test

    – charlietfl
    Nov 19 '18 at 15:54







    What's wrong with that case? uniqueVals would be [5,4,8]. All the values have to pass OP's isNan test

    – charlietfl
    Nov 19 '18 at 15:54















    didn't realise it would be such a simple fix, thank you

    – user8758206
    Nov 19 '18 at 16:09





    didn't realise it would be such a simple fix, thank you

    – user8758206
    Nov 19 '18 at 16:09











    1














    The function does not fail in the sense that it throws an error. For these types of questions please add an example of "expected results".



    When you compare strings and numbers in JavaScript, you are relying on implicit coercion to take care of the comparison. In this case it won't throw and error and break anything, it is fine as JavaScript will convert your string to a number and compare (unless its a strict equality === which checks type as well).



    Should the result be based off what was passed in? Or after the input has been filtered for numbers only. Or if the input can be converted to valid numbers?



    In the case of filter for valid numbers. Filter the input as follows...



      arr = arr.filter(data => typeof data === 'number')


    In the case of converting values to a number and removing those that cannot be converted...



      arr = arr.reduce(((acc, el) => {
    const num = Number(el);
    if (!Number.isNaN(num)) acc.push(num);
    return acc;
    }), );





    share|improve this answer




























      1














      The function does not fail in the sense that it throws an error. For these types of questions please add an example of "expected results".



      When you compare strings and numbers in JavaScript, you are relying on implicit coercion to take care of the comparison. In this case it won't throw and error and break anything, it is fine as JavaScript will convert your string to a number and compare (unless its a strict equality === which checks type as well).



      Should the result be based off what was passed in? Or after the input has been filtered for numbers only. Or if the input can be converted to valid numbers?



      In the case of filter for valid numbers. Filter the input as follows...



        arr = arr.filter(data => typeof data === 'number')


      In the case of converting values to a number and removing those that cannot be converted...



        arr = arr.reduce(((acc, el) => {
      const num = Number(el);
      if (!Number.isNaN(num)) acc.push(num);
      return acc;
      }), );





      share|improve this answer


























        1












        1








        1







        The function does not fail in the sense that it throws an error. For these types of questions please add an example of "expected results".



        When you compare strings and numbers in JavaScript, you are relying on implicit coercion to take care of the comparison. In this case it won't throw and error and break anything, it is fine as JavaScript will convert your string to a number and compare (unless its a strict equality === which checks type as well).



        Should the result be based off what was passed in? Or after the input has been filtered for numbers only. Or if the input can be converted to valid numbers?



        In the case of filter for valid numbers. Filter the input as follows...



          arr = arr.filter(data => typeof data === 'number')


        In the case of converting values to a number and removing those that cannot be converted...



          arr = arr.reduce(((acc, el) => {
        const num = Number(el);
        if (!Number.isNaN(num)) acc.push(num);
        return acc;
        }), );





        share|improve this answer













        The function does not fail in the sense that it throws an error. For these types of questions please add an example of "expected results".



        When you compare strings and numbers in JavaScript, you are relying on implicit coercion to take care of the comparison. In this case it won't throw and error and break anything, it is fine as JavaScript will convert your string to a number and compare (unless its a strict equality === which checks type as well).



        Should the result be based off what was passed in? Or after the input has been filtered for numbers only. Or if the input can be converted to valid numbers?



        In the case of filter for valid numbers. Filter the input as follows...



          arr = arr.filter(data => typeof data === 'number')


        In the case of converting values to a number and removing those that cannot be converted...



          arr = arr.reduce(((acc, el) => {
        const num = Number(el);
        if (!Number.isNaN(num)) acc.push(num);
        return acc;
        }), );






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 19 '18 at 16:25









        Sunny WongSunny Wong

        866




        866






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53377992%2fwhy-does-passing-in-a-number-as-a-string-into-an-array-cause-the-wrong-result%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

            ComboBox Display Member on multiple fields

            Is it possible to collect Nectar points via Trainline?