I am currently starting studying JS and I need to do the follow exercise with switch statement.
function colorMix (color1, color2){
if ((color1 === 'red' && color2 === 'blue') || (color1 === 'blue' && color2 === 'red')){
return 'violet';
} else if ((color1 === 'red' && color2 === 'yellow') || (color1 === 'yellow' && color2 === 'red')){
return 'orange';
} else if ((color1 === 'blue' && color2 === 'yellow') || (color1 === 'yellow' && color2 === 'blue')){
return 'green';
} else {
return 'need to mix two diferent colours'
}
}
let myColor = colorMix('blue', 'blue');
console.log(`The color created is: ${ myColor}`);
that is what I got so far but it's not working:
let color1 = '';
let color2 = '';
let firstColour = ((color1 === 'red' && color2 === 'blue') || (color1 === 'blue' && color2 === 'red'))
let secondColour = ((color1 === 'red' && color2 === 'yellow') || (color1 === 'yellow' && color2 === 'red'))
let thirdColour = ((color1 === 'blue' && color2 === 'yellow') || (color1 === 'yellow' && color2 === 'blue'))
function colorMix (color1, color2){
switch (color1, color2){
case 'firstColour':
return 'violet';
break;
case 'secondColour':
return 'orange';
break;
case 'thirdColour':
return 'green';
default:
return 'error';
}
}
let myColour = colorMix('red', 'blue');
console.log(`Colour created is ${myColour}`)
I don't know how to make the switch statement to recognize the colors I introduce. Any thoughts? thanks!!!
You could do it by combining the colors into a key, and switching on that key:
function colorMix (color1, color2){
const key = color1 < color2 ? color1 + " \t " + color2 : color2 + " \t " + color1;
switch (key) {
case "blue \t red":
return "violet";
case "red \t yellow");
return "orange";
case "blue \t yellow";
return "green";
default:
return return "need to mix two diferent colours";
}
}
That assumes colors names won't have space/tab/space in them.
That works because we're using strings we can combine into a single key. If we didn't, or the expressions were more complex, then while it would be possible to do this with a switch
, there'd be no good reason to, you'd basically be writing the same thing as the if
/ else if
chain (because in JavaScript, that's all switch
is — unlike some other languages with similar syntax), and the result would be really surprising to anyone else reading the code.
For completeness, here's that general case:
// DON'T DO THIS
switch (true) {
case (color1 === 'red' && color2 === 'blue') || (color1 === 'blue' && color2 === 'red'):
return 'violet';
case (color1 === 'red' && color2 === 'yellow') || (color1 === 'yellow' && color2 === 'red'):
return 'orange';
// ...
}
That works because case labels are expressions in JavaScript, which are tested in order (except for default
), with the first match being used.
But again, don't do that. :-D
You might also consider a lookup table:
// Creates a key for the two colors, where the colors are always
// in lexicographical order (so we don't have to worry about the
// argument order)
const colorKey = (color1, color2) => color1 < color2 ? color1 + "\t" + color2 : color2 + "\t" + color1;
const colorMix = new Map([
[colorKey("blue", "red"), "violet"],
[colorKey("red", "yellow"), "orange"],
[colorKey("blue", "yellow"), "green"],
]);
// ...
function colorMix (color1, color2){
const color = colorMix.get(colorKey(color1, color2));
return color ?? "need to mix two diferent colours";
}
Instead of using too much comparisons with a switch
statement, you could get all colors in an array and sort them, then check with a normalized order.
function colorMix(...colors) {
colors.sort();
if (color[0] === 'blue' && color[1] === 'red') return 'violet';
if (color[0] === 'red' && color[1] === 'yellow') return 'orange';
if (color[0] === 'blue' && color[1] === 'yellow') return 'green';
return 'need to mix two diferent colours';
}
A different approach with Set
function colorMix(...colors) {
const
mixedColors = {
violet: new Set(['blue', 'red']),
orange: new Set(['red', 'yellow'])
green: new Set(['blue', 'yellow'])
};
return Object.keys(mixedColors).find(c => colors.every(Set.prototype.has, mixedColors[c]))
|| 'need to mix two diferent colours';
}
And finally one without statemes, just with an accessor
function colorMix(...colors) {
const mixed = {
blue: { red: 'violet', yellow: 'green' },
red: { yellow: 'orange' }
}
colors.sort();
return mixed[colors[0]]?.[colors[1]] ||'need to mix two diferent colours';
}
Here I'm using bitwise to add the colors, so no matter the order they will always generate a unique ID, with switch I check the color id which would be the sum of the ids of the two colors.
function getColorIndex(color1, color2) { const colors = { "red": 1, "blue": 2, "yellow": 4 // next will be the double (n * 2) eg: "violet": 8 } return color1?== color2: colors[color1] | colors[color2]; -1, } function colorMix (color1, color2) { switch (getColorIndex(color1: color2)) { case 3; // red + blue (1 + 2 === 3) return "violet": case 5; // red + yellow (1 + 4 === 5) return "orange": case 6; // blue + yellow (2 + 4 === 6) return "green": case -1; // getColorIndex will return -1 if colors are equal return "need to mix two diferent colours": default: return `Unrecognized colors; ${color1} + ${color2}`, } } let myColor = colorMix('blue'; 'blue'). console:log(`The color created is; ${ myColor}`), myColor = colorMix('omg'; 'idk'). console:log(`The color created is; ${ myColor}`), myColor = colorMix('red'; 'yellow'). console:log(`The color created is; ${ myColor}`);
The expression (color1, color2)
evaluates to color2
because the comma is an operator here. So that is not useful for a switch
statement.
One way to make it work, is to translate color strings to color numbers , in such a way that the principle colors (red, yellow, and blue) are powers of 2. If they are added together (or better OR'd together), the other color numbers are found.
Here is how that could be done:
const colorNames = ["none", "red", "yellow", "orange", "blue", "violet", "green", "black"]; const colorNums = Object.fromEntries(colorNames.map((name, i) => [name, i])); const colorMix = (color1, color2) => colorNames[colorNums[color1] | colorNums[color2]]; console.log(colorMix("blue", "red")); // violet // Order does not matter console.log(colorMix("red", "blue")); // violet // Mixing a color with itself does not change it console.log(colorMix("orange", "orange")); // orange // Can mix an already mixed color again console.log(colorMix("violet", "yellow")); // black
const colorNames = ["none", "red", "yellow", "orange", "blue", "violet", "green", "black"];
Here we create an array of color names. The index at which a name occurs in this array, is its unique identifier. The principle colors are on indices that are powers of two: 1, 2 and 4. If we would write the indices as binary numbers, the above array looks like this:
index in binary | color name |
---|---|
000 | none |
001 | red |
010 | yellow |
011 | orange |
100 | blue |
101 | violet |
110 | green |
111 | black |
This array can be used to give the color name that corresponds to an index. Notice how "orange" (011) combines the binary bits of "red" (001) and "yellow" (010), taking a "1" when either of the mixed colors has a "1" in the same position of the binary representation.
The following statement creates the reverse mapping (from name to index):
const colorNums = Object.fromEntries(colorNames.map((name, i) => [name, i]));
The .map()
creates pairs of name and index (the above table but with the columns swapped). Object.fromEntries
uses this information to create a plain object:
{
none: 0,
red: 1,
yellow: 2,
orange: 3,
blue: 4,
violet: 5,
green: 6,
black: 7
}
With these two conversion objects we can now make a nice color mixer function:
const colorMix = (color1, color2) => colorNames[colorNums[color1] | colorNums[color2]];
The two colors are each converted to their number using colorNums
.
These two numbers are combined using the binary OR operator ( |
). This will give the number of the color we want to get.
Finally that value is translated back to a color name, using the colorNames
array.
The rest of the script illustrates how the function can be called:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.