Javascript reads only first elements(from array) in nested for loops

1.5k views Asked by At

I have the following issue. There's a problem I have to solve.

Fruit or Vegetable Write a JS function to print "fruit" , "vegetable" or "unknown" depending on the input string.

  • Fruits are: banana, apple, kiwi, cherry, lemon, grapes, peach

  • Vegetable are: tomato, cucumber, pepper, onion, garlic, parsley

  • All others are unknown

    The input comes as array of one string element, the name of the fruit. The output should be printed to the console.

Example: input ['banana'] output: fruit
Example: input ['cucumber'] output: vegetable
Example: input ['pizza'] output: unknown

and I've tried something like that.

function fruitOrVegetable(inputArr) {
  var fruits = ['banana', 'apple', 'kiwi', 'cherry', 'lemon', 'grapes', 'peach'];
  var vegetables = ['tomato', 'cucumber', 'pepper', 'onion', 'garlic', 'parsley'];

  for (var i = 0; i < inputArr.length; i++) {
    for (var j = 0; j < fruits.length; j++) {
      for (var k = 0; k < vegetables.length; k++) {
        if (inputArr[i] === fruits[j]) {
          return ' fruit ';
        } else if (inputArr[i] === vegetables[k]) {
          return 'vegetable';
        } else {
          return 'unknown';
        }
      }
    }
  }
}

console.log(fruitOrVegetable(['tomato'])); //Returns vegetable
console.log(fruitOrVegetable(['banana'])); //Returns fruit
console.log(fruitOrVegetable(['cucumber'])); //Returns unknown
console.log(fruitOrVegetable(['pizza'])); // Returns unknown
console.log(fruitOrVegetable(['appple'])); //Returns unknown

Don't know why , but it works only for the 0 index of the array , for example , for 'tomato' it returns vegetable , but if I try it for the other vegetables , it returns unknown. If I remove that last statement

else{
 return false;
}

Then , cucumber becomes vegetable , but apple gots undefined? I'm a bit confused , so I'll be glad if someone explain me why this happens. Thank you.

7

There are 7 answers

2
choz On BEST ANSWER

You're doing a massive nested unnecessary for loop there. The task is pretty straightforward

The input comes as array of one string element, the name of the fruit. The output should be printed to the console.

You just have to grab that first inputArr value, which is a string and check if its value actually in your fruits, vegetables or else unknown.

Something like,

function fruitOrVegetable(inputArr) {
    var fruits = ['banana', 'apple', 'kiwi', 'cherry', 'lemon', 'grapes', 'peach'];
    var vegetables = ['tomato', 'cucumber', 'pepper', 'onion', 'garlic', 'parsley'];

    var val = inputArr[0];

    return fruits.indexOf(val) !== -1 ? 'fruit' : vegetables.indexOf(val) !== -1 ? 'vegetables' : 'unknown';
}

Edit:

Let's break the code above,

// This is to grab the string from the first value in `inputArr` and store in `val`.
var val = inputArr[0];

And returning,

1 fruits.indexOf(val) !== -1 ? 'fruit' :

2 vegetables.indexOf(val) !== -1 ? 'vegetables' :

3 'unknown';

  1. Check whether val exists in fruits, if it does, return 'fruit' or else run 2
  2. Check whether val exists in vegetables, if it does, return 'vegetables' or else run 3
  3. Return 'undefined'

This operation equals to,

if (fruits.indexOf(val) !== -1) {
    return 'fruit';
}
else if (vegetables.indexOf(val) !== -1) {
    return 'vegetables';
}
else {
    return 'unknown';
}

More info:

?: is a conditional (ternary) operator. (Read more here). It's pretty handy to evaluate expression

e.g.

var myval = 1;
console.log(myval ? 'true' : 'false'); // true

myval = false;
console.log(myval ? 'true' : 'false'); // false

indexOf is an array native function, which you can check the index of a value in an array. (Read more here)

e.g.

var myarr = ['test', 'tost', 'aww'];
console.log(myarr.indexOf('tost')); // returns 1
console.log(myarr.indexOf('tosts')); // returns -1 (value not found)
1
Gaurav joshi On

function fruitOrVegetable(inputArr) {
  var fruits = ['banana', 'apple', 'kiwi', 'cherry', 'lemon', 'grapes', 'peach'];
  var vegetables = ['tomato', 'cucumber', 'pepper', 'onion', 'garlic', 'parsley'];
  
  if(inputArr === undefined || !inputArr.length) return 'unknown';

  if(fruits.indexOf(inputArr[0]) !== -1) return 'fruit';
  if(vegetables.indexOf(inputArr[0]) !== -1) return 'vegetable';
  return 'unknown';
}

console.log(fruitOrVegetable(['banana']));
console.log(fruitOrVegetable(['tomato']));
console.log(fruitOrVegetable(['xxx']));
console.log(fruitOrVegetable([]));
console.log(fruitOrVegetable());

0
thefourtheye On

Suggestions:

  1. Check if the current item is a fruit and only if you made sure that it is not a fruit, check if it is a vegetable.

  2. Return unknown only after confirming if the current item is neither a fruit nor a vegetable.


function fruitOrVegetable(inputArr) {
  var fruits = ['banana', 'apple', 'kiwi', 'cherry', 'lemon', 'grapes', 'peach'];
  var vegetables = ['tomato', 'cucumber', 'pepper', 'onion', 'garlic', 'parsley'];

  var result = [];
  for (var i = 0; i < inputArr.length; i++) {

    var isFruit = false;
    var isVegetable = false;

    for (var j = 0; j < fruits.length; j++) {
      if (inputArr[i] === fruits[j]) {
        result.push('fruit');
        isFruit = true;
        break;
      }
    }

    if (isFruit) {
      // skip rest of the body of the loop as it is a Fruit
      continue;
    }

    for (var j = 0; j < vegetables.length; j++) {
      if (inputArr[i] === vegetables[j]) {
        result.push('vegetable');
        isVegetable = true;
        break;
      }
    }

    if (isVegetable === false) {
      // at this point we know its neither a fruit nor a vegetable
      result.push('unknown');
    }

  }
  return result;
}

console.log(fruitOrVegetable(['tomato', 'banana', 'cucumber', 'pizza', 'apple']));
// [ 'vegetable', 'fruit', 'vegetable', 'unknown', 'fruit' ]

Improvements with Array#indexOf

JavaScript Arrays come with a lot of built-in methods which will help is with basic sorting and searching. You can use the Array.prototype.indexOf to find the index of an element in an array. It will return -1 if it is not found. If we rewrite with that information,

function fruitOrVegetable(inputArr) {
  var fruits = ['banana', 'apple', 'kiwi', 'cherry', 'lemon', 'grapes', 'peach'];
  var vegetables = ['tomato', 'cucumber', 'pepper', 'onion', 'garlic', 'parsley'];

  var result = [];
  for (var i = 0; i < inputArr.length; i += 1) {
    if (fruits.indexOf(inputArr[i]) !== -1) {
      result.push('fruit');
    } else if (vegetables.indexOf(inputArr[i]) !== -1) {
      result.push('vegetable');
    } else {
      result.push('unknown');
    }
  }
  return result;
}

console.log(fruitOrVegetable(['tomato', 'banana', 'cucumber', 'pizza', 'apple']));
// [ 'vegetable', 'fruit', 'vegetable', 'unknown', 'fruit' ]

Improvements with Array#indexOf and Array#map

Now, you can write the same with functional programming approach. You can apply a function to each of the elements of inputArr with Array.prototype.map, like this

function fruitOrVegetable(inputArr) {
  var fruits = ['banana', 'apple', 'kiwi', 'cherry', 'lemon', 'grapes', 'peach'];
  var vegetables = ['tomato', 'cucumber', 'pepper', 'onion', 'garlic', 'parsley'];

  return inputArr.map(function(currentItem) {
    if (fruits.indexOf(currentItem) !== -1) {
      return 'fruit';
    } else if (vegetables.indexOf(currentItem) !== -1) {
      return 'vegetable';
    }
    return 'unknown';
  });
}

console.log(fruitOrVegetable(['tomato', 'banana', 'cucumber', 'pizza', 'apple']));
// [ 'vegetable', 'fruit', 'vegetable', 'unknown', 'fruit' ]
3
a-man On

Short answer: You have misplaced return "unknown". Consider this:

function fruitOrVegetable(inputArr) {
 var fruits = ['banana', 'apple', 'kiwi', 'cherry', 'lemon', 'grapes', 'peach'];
 var vegetables = ['tomato', 'cucumber', 'pepper', 'onion', 'garlic', 'parsley'];

for (var i = 0; i < inputArr.length; i++) {
  for (var j = 0; j < fruits.length; j++) {
    for (var k = 0; k < vegetables.length; k++) {
      if (inputArr[i] === fruits[j]) {
        return ' fruit ';
      } else if (inputArr[i] === vegetables[k]) {
        return 'vegetable';}
      }
    }
  }
return "unknown";
}

Updated answer according to comments

  1. Don't know why , but it works only for the 0 index of the array

Reason is you are returning value right inside of your loop. So it never runs to the end. To fix that put return "unknown"; outside of the loop.

  1. In general you have messed with loops and code should be simplified. You can ask for code review whenever you think your code can be better, but you don't know how to do that.
  2. It is good practice to simplify code to never get confused with it. For example you could write as below:

     function isVegetable(inputArr)
     {
        var vegetables = ['tomato', 'cucumber', 'pepper', 'onion', 'garlic', 'parsley'];        
    
       for (var i = 0; i < inputArr.length; i++) {
         for (var k = 0; k < vegetables.length; k++) {
            if (inputArr[i] === vegetables[k]) {
              return true;
            }
          }
        }
      return false;
      }
    
    
     function isFruit(inputArr)
     {
          var fruits = ['banana', 'apple', 'kiwi', 'cherry', 'lemon', 'grapes', 'peach'];
    
        for (var i = 0; i < inputArr.length; i++) {
        for (var k = 0; k < fruits.length; k++) {
            if (inputArr[i] === fruits[k]) {
                return true;
                }
            }
         }
        return false;
     }
    
     function fruitOrVegetable(inputArr)
     {
         if(isVegetable(inputArr)) return "vegetable";  
         if(isFruit(inputArr)) return "fruit";
         return "unknown";
     }
    
0
udarabibile On

First of all return vegetable is the reason why it's only working for index 0. Because after first loop it returns a value and function ends. Instead initialize outputArray at start and set values to that array outputArray[i] = 'veg' and at the end return outputArray
Next thing is don't nest too much loops within each other. Instead use check for veg or fruit separately inside large for loop:
for() {...} for() {...}
Sorry couldn't complete codes cause I'm writing from my phone

0
black_pottery_beauty On

You can try this way if it wil be preferable to you:-

function fruitOrVegetable(inputArr) {
  var fruits = ['banana', 'apple', 'kiwi', 'cherry', 'lemon', 'grapes', 'peach'];
  var vegetables = ['tomato', 'cucumber', 'pepper', 'onion', 'garlic', 'parsley'];

  if ( fruits.indexOf( inputArr[0] ) > -1 ){
     return 'fruits';
  }else if ( vegetables.indexOf( inputArr[0] ) > -1 ){
     return 'vegetable';
  }else{
     return 'unknown';
  }
}
0
gopi chand Puli On

Modify your code like this, it will work file.

function fruitOrVegetable(inputArr) {

    var fruits = ['banana' , 'apple' , 'kiwi' , 'cherry' , 'lemon' , 'grapes' , 'peach'];
    var vegetables = ['tomato' , 'cucumber' , 'pepper' , 'onion' , 'garlic' , 'parsley'];

    for(var i = 0 ; i < inputArr.length ; i++)
    {
        for(var j = 0 ; j < fruits.length ; j++)
        {
            if(inputArr[i] === fruits[j]){
                    return ' fruit ';
                    }
        }
        for(var k = 0 ; k < vegetables.length ; k++)
        {

                 if(inputArr[i] === vegetables[k]){
                    return 'vegetable';
                }

        }

    }
                  return 'unknown';
}  

Result:

fruitOrVegetable(['tomato']); "vegetable" fruitOrVegetable(['banana']); " fruit "

fruitOrVegetable(['qwe']); "unknown"