最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Javascript: I am trying to use a switch statement to push strings to a new array - Stack Overflow

programmeradmin1浏览0评论

Here's the challenge: Write a function that takes in a fruit array and return an array of colors that can be found in this array. Fruits of the same color will return the same value but not repeat itself.

For example:

whatFruitColors(['apple', 'orange', 'mango']);
// returns ['red', 'orange']

I am trying to solve this with a switch statement because I would like to use "fall-through" to process all the statements. Can someone please tell me what I am doing wrong?

    var whatFruitColors = function(fruitArray){
  var fruitColors = [];

    switch(fruitArray){
      case fruitArray.indexOf('pineapple' || 'banana') > -1):
        fruitColors.push('yellow');

      case fruitArray.indexOf('mango' || 'orange') > -1):
        fruitColors.push('orange');

      case fruitArray.indexOf('apple') > -1):
        fruitColors.push('red');

      break;
  }

  console.log(fruitColors);
  return fruitColors;

}

whatFruitColors(['pineapple','banana','apple','mango','orange']);

Here's the challenge: Write a function that takes in a fruit array and return an array of colors that can be found in this array. Fruits of the same color will return the same value but not repeat itself.

For example:

whatFruitColors(['apple', 'orange', 'mango']);
// returns ['red', 'orange']

I am trying to solve this with a switch statement because I would like to use "fall-through" to process all the statements. Can someone please tell me what I am doing wrong?

    var whatFruitColors = function(fruitArray){
  var fruitColors = [];

    switch(fruitArray){
      case fruitArray.indexOf('pineapple' || 'banana') > -1):
        fruitColors.push('yellow');

      case fruitArray.indexOf('mango' || 'orange') > -1):
        fruitColors.push('orange');

      case fruitArray.indexOf('apple') > -1):
        fruitColors.push('red');

      break;
  }

  console.log(fruitColors);
  return fruitColors;

}

whatFruitColors(['pineapple','banana','apple','mango','orange']);
Share Improve this question edited Feb 21, 2017 at 5:57 nnnnnn 150k30 gold badges209 silver badges247 bronze badges asked Feb 21, 2017 at 5:37 Colin SygielColin Sygiel 9456 gold badges19 silver badges31 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 3

If you need a much less elegant solution than Array.reduce, then:

    var whatFruitColors = function (fruitArray) {
        var fruitColors = [];

        for (var i = 0; i < fruitArray.length; i++) {
            var item = fruitArray[i];
            switch (item) {
                case 'pineapple':
                case 'banana':
                    if (fruitColors.indexOf('yellow') === -1) {
                        fruitColors.push('yellow');    
                    }
                    break;
                case 'mango':
                case 'orange':
                    if (fruitColors.indexOf('orange') === -1) {
                        fruitColors.push('orange');
                    }
                    break;
                case 'apple':
                    if (fruitColors.indexOf('red') === -1) {
                        fruitColors.push('red');
                    }
                    break;
            }
        }

        console.log(fruitColors);

        return fruitColors;
    };

    whatFruitColors(['pineapple', 'banana', 'apple', 'mango', 'orange']);

Others have explained where you went wrong, but I thought I'd add an answer to show that sometimes when you are trying to create an array without duplicates it can be simpler to use a plain object as a working variable and then just take the keys from that object at the end - saves having to do any testing of whether a particular item already exists.

If you have:

var fruits = {};

...then you can say:

fruits['yellow'] = true;

...as many times as you like and the fruits object will still have only one property named yellow. (The value you assign to the property can be anything, because the point is just to create the property, but I suggest true because it seems more logical than other possible values.)

In context (still using a switch statement, though you could do this with .reduce() or a series of if statements or whatever the other answer did):

var whatFruitColors = function(fruitArray){
  var fruitColors = {};

  fruitArray.forEach(function(fruit) {
    switch(fruit){
      case 'pineapple':
      case 'banana':
        fruitColors['yellow'] = true;
        break;

      case 'mango':
      case 'orange':
        fruitColors['orange'] = true;
        break;

      case 'apple':
        fruitColors['red'] = true;
        break;
    }
  });
  console.log(fruitColors);
  return Object.keys(fruitColors);
}

console.log(whatFruitColors(['pineapple','banana','apple','mango','orange']));

I don't think switch is a good fit for this. And I think your "fall-through" pattern is guaranteed to fail: every case statement after the first that is triggered will also execute.

You can make this work with a switch, but you'd have to abandon your "fall-through," and you'll need to iterate through the individual fruits.

Alternatively, if you just want to avoid any looping, the most straightforward solution is to use a series of non-exclusive if statements, like so:

function whatFruitColors(fruitList) {
    var results = [];

    if(fruitList.indexOf('apple'    ) >= 0 && results.indexOf('red'   ) === -1) fruitList.push('red'   );
    if(fruitList.indexOf('banana'   ) >= 0 && results.indexOf('yellow') === -1) fruitList.push('yellow');
    if(fruitList.indexOf('kiwi'     ) >= 0 && results.indexOf('green' ) === -1) fruitList.push('green' );
    if(fruitList.indexOf('mango'    ) >= 0 && results.indexOf('orange') === -1) fruitList.push('orange');
    if(fruitList.indexOf('orange'   ) >= 0 && results.indexOf('orange') === -1) fruitList.push('orange');
    if(fruitList.indexOf('pineapple') >= 0 && results.indexOf('yellow') === -1) fruitList.push('yellow');

    return results;
}

whatFruitColors(['pineapple','banana','apple','mango','orange']);

This will work, but it's frankly crude, and there's a lot of redudant code. Also, maintaining this -- i.e. adding new fruits, maintaining the list of fruit+color associations -- will be a pain in the ass.

This is a perfect use-case for Array.reduce. Here is a better solution:

function whatFruitColors(fruitList) {
    // a static lookup "table" that declares the color of every fruit
    var FRUIT_COLORS = {
        'apple': 'red',
        'banana': 'yellow',
        'kiwi': 'green',
        'mango': 'orange',
        'orange': 'orange',
        'pineapple': 'yellow'
    };

    return fruitList.reduce(function(foundColors, thisFruit) {
        var thisFruitColor = FRUIT_COLORS[thisFruit];
        if(foundColors.indexOf(thisFruitColor) === -1) {
            foundColors.push(thisFruitColor);
        }

        return foundColors;
    }, []);
}

whatFruitColors(['pineapple','banana','apple','mango','orange']);

Not quite what you were looking for -- and not as elegant as Tom's solution, wow -- but it does use a switch statement. (I thought about putting the conditionals in the switch cases, but it seemed neater to just filter the result at the end.)

var whatFruitColors = function(fruitArray){
  var fruitColors = [];
    for (let fruit of fruitArray) {
    switch(fruit){
      case 'pineapple':
      case 'banana':
        fruitColors.push('yellow');
            break;
      case 'mango':
      case 'orange':
        fruitColors.push('orange');
            break;
      case 'apple':
        fruitColors.push('red');
            break;
    }
  }
    let reducedFruits = fruitColors.filter((elem, index, self) => {
       return index === self.indexOf(elem);
    });
  console.log(reducedFruits);
  return reducedFruits;

}

whatFruitColors(['pineapple','banana','apple','mango','orange']);

Seems like you're trying to use a switch statement for no real reason, when simple if statements would suffice. This will give you the "fall-through" flow that you want, because it's just a series of statements.

Also, using 'oneValue' || 'anotherValue' inside .indexOf won't do what you're trying to do. fruitArray.indexOf('pineapple' || 'banana') is functionally identical to fruitArray.indexOf('pineapple'). The 'banana' part will be ignored.

var whatFruitColors = function(fruitArray) {
  var fruitColors = [];

  if (fruitArray.indexOf('pineapple') > -1 ||
      fruitArray.indexOf('banana') > -1) {
    fruitColors.push('yellow');
  }

  if (fruitArray.indexOf('mango') > -1 ||
      fruitArray.indexOf('orange') > -1) {
    fruitColors.push('orange');
  }

  if (fruitArray.indexOf('apple') > -1) {
    fruitColors.push('red');
  }

  console.log(fruitColors);
  return fruitColors;
}

whatFruitColors(['pineapple', 'banana', 'apple', 'mango', 'orange']);

You could also use a cleaner and more extensible implementation that uses .filter, .some, and .map:

function whatFruitColors(fruits) {
  var fruitColors = [{
      color: 'red',
      fruits: ['apple']
    },
    {
      color: 'yellow',
      fruits: ['banana', 'pineapple']
    },
    {
      color: 'orange',
      fruits: ['mango', 'orange']
    }
  ];

  return fruitColors.filter(function(item) {
      return item.fruits.some(function(fruit) {
        return fruits.indexOf(fruit) > -1;
      });
    })
    .map(function(item) {
      return item.color;
    });
}

console.log(whatFruitColors(['banana', 'mango', 'orange']));

发布评论

评论列表(0)

  1. 暂无评论