Koji E
Koji E

Reputation: 99

Switch Statement: Applying Multiple Arguments in One Output

I am trying to figure out how I can apply two different conditions to one output in a switch statement. For example, I have a function to style a string depending on what arguments that 2nd parameter gets. The first and second output is okay since it only has one argument for styling but the third output does. I cannot find a way to apply both uppercase and reversed styling to a string. I've tried to loop a switch statement. I'd like to know if there are any good solutions for this.

function caseStyle(string, style) {
  function toUpper(string) {
    string = string.toUpperCase();
    return string;
  }

  function toReversed(string) {
    string = string.split("").reverse().join("");
    return string;
  }

  switch (style) {
    case "upper":
      string = toUpper(string);
      break;
    case "reversed":
      string = toReversed(string);
      break;
  }
  return string;
}

console.log(caseStyle("hello", "upper")); //output: HELLO
console.log(caseStyle("hello", "reversed")); //output: olleh
console.log(caseStyle("hello", ["upper", "reversed"])); // expected output: OLLEH

Upvotes: 2

Views: 76

Answers (4)

Roko C. Buljan
Roko C. Buljan

Reputation: 206344

Besides some to-the-point answers in here...
I'd present a different approach:

  • Move the inner functions toUpper and toReversed outside of your caseStyle function. There's no need to have them in there
  • Use Arrow Functions and implicit return instead of doing twice(!) str = str... in the method functions and again in the switch case
  • Group your functions into an Object called methods - and name your functions exactly like their string names-references
  • Instead of a switch-case, use Array.prototype.reduce()
  • Instead of wrapping your String/or/Array logic into an if statement, always force the second array (btw, rename it to styles, plural) to always be an Array by converting the string into Array. Even more, by using .split(/\W+/) (split by one or more non-word characters) you can now also pass a string like "upper,reversed"
  • Thanks to this logic you're decoupling your methods and you can add more at any point in time, an you can use in the future the expected methods (transformation) names you have available like i.e: caseStyle("hello", ["snake", "capitalize", "reverse"]) or more.

const methods = {
  upper: str => str.toUpperCase(),
  reversed: str => [...str].reverse().join(""),
};

const caseStyle = (str, styles) => {
  if (typeof styles === "string") styles = styles.split(/\W+/);
  return styles.reduce((acc, style) => methods[style](acc), str);
};

console.log(caseStyle("hello", "upper")); //output: HELLO
console.log(caseStyle("hello", "reversed")); //output: olleh
console.log(caseStyle("hello", ["upper", "reversed"])); // expected output: OLLEH
console.log(caseStyle("stack", "reversed upper")); // expected output: KCATS

As you can notice from the above, I've used the preferred string Spread syntax [...str] to convert a String to Array. One might run into problems when using .split("") on a string that uses more than one code point to represent a glyph, like i.e: Emoji:

Issue when using .split("")

console.log("ab📆🔞".split(""))

will give: ["a","b","�","�","�","�"]

Better string split: using Spread syntax:

console.log([..."ab📆🔞"])

as you can see the emojis are correctly split and preserved.

Upvotes: 1

NirG
NirG

Reputation: 776

You can use switch (true) in the following way:

function caseStyle(string, style) {
      function toUpper(string) {
        string = string.toUpperCase();
        return string;
      }

  function toReversed(string) {
    string = string.split("").reverse().join("");
    return string;
  }

  switch (true) {
    case style === "upper":
      string = toUpper(string);
      break;
    case style === "reversed":
      string = toReversed(string);
      break;
    case style.includes("upper") && style.includes("reversed"):
      string = toUpper(toReversed(string))
      break;
    default:
       break;
  }
  return string;
}

console.log(caseStyle("hello", "upper"));//output: HELLO
console.log(caseStyle("hello", "reversed"));//output: olleh
console.log(caseStyle("hello", ["upper", "reversed"]));// expected output: OLLEH

Upvotes: 1

Michael M.
Michael M.

Reputation: 11080

Why don't you just run a simple for-of-loop? You'll also need to check if the input isn't an array, then turn it into an array if it isn't already.

function caseStyle(string, styles) {
  function toUpper(string) {
    string = string.toUpperCase();
    return string;
  }

  function toReversed(string) {
    string = string.split("").reverse().join("");
    return string;
  }
  
  if (!(styles instanceof Array)) styles = [styles];
  for (const style of styles) {
    switch (style) {
      case "upper":
        string = toUpper(string);
        break;
      case "reversed":
        string = toReversed(string);
        break;
    }
  }
  return string;
}

console.log(caseStyle("hello", "upper")); //output: HELLO
console.log(caseStyle("hello", "reversed")); //output: olleh
console.log(caseStyle("hello", ["upper", "reversed"])); // expected output: OLLEH

Upvotes: 0

Jaromanda X
Jaromanda X

Reputation: 1

you'd need to check if style is an array, and handle accordingly

Or, force it to be an Array style = [style].flat() and then iterate that array

The .flat() will flatten the array in the case when an array is passed in

as follows

function caseStyle(string, style) {
  style = [style].flat();
  function toUpper(string) {
    string = string.toUpperCase();
    return string;
  }

  function toReversed(string) {
    string = string.split("").reverse().join("");
    return string;
  }
  style.forEach(style => {
    switch (style) {
      case "upper":
        string = toUpper(string);
        break;
      case "reversed":
        string = toReversed(string);
        break;
    }
  });
  return string;
}

console.log(caseStyle("hello", "upper")); //output: HELLO
console.log(caseStyle("hello", "reversed")); //output: olleh
console.log(caseStyle("hello", ["upper", "reversed"])); // expected output: OLLEH

Upvotes: 2

Related Questions