2
$\begingroup$

I'm currently trying a function that behaves differently depending on what kind of Type string you enter. This string can have six different values, let's say "A", "B", "C", "D", "E" and "F". What I want to construct is an if statement of the form

f[Type_]:=
     If[Type!="A"||"B"||"C"||"D",
          1,
          0
     ]

So basically this is a function that yields the value 0 if I enter types "A" through "D" but 1 for the two remaining types "E" and "F".

The problem with the above code is that this apparently is not the right way to make a multiple comparison for the function string Type.

Note, I know about the Switch[] function, but this is nog sufficient for my case.

$\endgroup$
  • $\begingroup$ There's no such thing as an "if loop". Looping means repetition. What does If repeat? Or (i.e. ||) connects a series of statements, each of which can be true or false. Thus this use is incorrect. The simplest solution is Switch because it uses patterns and you can use Alternatives. Don't simply just state that "Switch is not sufficient", explain why. $\endgroup$ – Szabolcs Nov 4 '16 at 11:31
  • 1
    $\begingroup$ perhaps MemberQ[{"A","B","C","D"},Type] will do $\endgroup$ – george2079 Nov 4 '16 at 11:34
  • 3
    $\begingroup$ @george2079 But it will always be slower than pattern matching like Switch[Type, "A" | "B" | "C" | "D", 0, _, 1 ]. $\endgroup$ – Szabolcs Nov 4 '16 at 11:38
  • $\begingroup$ @Szabolcs, That actually solves my problem! My idea was that switch only took a function value depending on one argument, not multiple! Your comment is for me an answer. Is it perhaps possible to elaborate on how this switch statement works ? $\endgroup$ – Nick Nov 4 '16 at 13:08
  • 2
    $\begingroup$ These methods are alternative ways to achieve the same goal, but if you really wanted to use Or for the sake of understanding how things work you could make several complete statements chained together: (Type=="A"||Type=="B"||..). Which you can do with: Or@@Thread[Equal[Type,{"A","B","C","D"}]] $\endgroup$ – N.J.Evans Nov 4 '16 at 13:29
5
$\begingroup$

A very simple but robust solution to this problem is to use multiple definitions.

f["A" | "B" | "C" | "D"] = 0;
f["E" | "F"] = 1;
f[___] = $Failed;

Then

f /@ CharacterRange["A", "H"]

gives

{0, 0, 0, 0, 1, 1, $Failed, $Failed}

$\endgroup$
  • $\begingroup$ Looks like an elegant solution! What does the f[type: ...] do exactly? I always assumed that f[x_]:= was the way to go for functional arguments? $\endgroup$ – Nick Nov 7 '16 at 13:03
  • $\begingroup$ @Dominique, Good question! It doesn't do anything. I mindlessly copied it from your question. Not only is type not needed, but SetDelayed can be replace by a simple Set. I have corrected my answer. $\endgroup$ – m_goldberg Nov 8 '16 at 2:40
  • $\begingroup$ OK, now I fully understand the answer :) $\endgroup$ – Nick Nov 9 '16 at 6:54
1
$\begingroup$

Some variants:

f[x_] := 1 - Boole[Or @@ (x == # & /@ CharacterRange["A", "D"])]
g[x_] := Boole[And @@ (x != # & /@ CharacterRange["A", "D"])]
h[x_] := x /. {(Alternatives @@ CharacterRange["A", "D"]) :> 0, 
   s_ :> 1}

e.g

test = RandomChoice[CharacterRange["A", "Z"], 20];
TableForm[{#, f@#, g@#, h@#} & /@ test, 
 TableHeadings -> {None, {"x", "f", "g", "h"}}]

enter image description here

$\endgroup$
  • $\begingroup$ Nice addition! I'll remember this one! $\endgroup$ – Nick Nov 9 '16 at 6:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.