9

So I'm making a method to create a salutation line based on two people from a database.

There are four parameters: the two names (name1 and name2) and the two genders (gender and gender2).

For every gender combination, I have a kind of different output.

For example: if gender 1 is M (man) and gender 2 is also M, the output should be something like:

Dear Sir name1 and Sir name2,

At this time, my switch looks like this:

switch(gender1){
    case 'M':
        switch(gender2){
            case 'M': printf("Dear Sir %s and Sir %s", name1, name2); break;
            case 'W': printf("Dear Sir %s and Madame %s", name1, name2); break;
            case 'R': ...
        }
        break;
    case 'W':
        switch(gender2){
            case 'M': printf("Dear Madame %s and Sir %s", name1, name2); break
            case 'W': printf("Dear Madame %s and Madame %s", name1, name2); break;
            case 'R': ...
        }
        break;
    case ...etc.
}

Note that I have multiple gender options, like 'R' for "Dear Relation" and some more that I do not have the time to translate.

How can I reduce this double switch statement?

Putting the second switch in a method is not an option because there is also a case where both of the names are the same and then the output should be combined like: "Dear Sir and Madame name1,"

moffeltje
  • 251
  • 3
  • 8
  • 5
    ["If the same switch starts to pop up in multiple places, polymorphism is probably the best option to unify all these cases and simplify code..."](http://programmers.stackexchange.com/a/147227/31260) – gnat Jul 14 '15 at 08:54
  • 1
    If your language allows it, switch on an expression that varies with *both* values, e.g. `gender1+gender2`. – Kilian Foth Jul 14 '15 at 09:03
  • 3
    On an unrelated point, the female title to use here is `Madam`, not `Madame`. `Madame` is the French form. – rojomoke Jul 14 '15 at 14:38
  • 3
    Slightly unnecessary, but that fact that your 'gender' variable can be 'male', 'female' or 'relation' is a bit disturbing... – Paddy Jul 14 '15 at 15:46
  • @paddy good thinking. In real life it is not called gender but salutation flag (brutally translated from Dutch). It was more for demonstration purposes ;) – moffeltje Jul 14 '15 at 15:49
  • 4
    _"Note that I have multiple gender options"_ Well, that's certainly in vogue these days... – Lightness Races in Orbit Jul 14 '15 at 20:32

6 Answers6

32

Add the title to the parameters of the printf:

char* title1;
switch(gender1){
    case 'M':
        title1 = "Sir";
        break;
    case 'W':
       title1 = "Madam";
        break;
    case ...etc.
}
char* title2;
switch(gender2){
    case 'M':
        title2 = "Sir";
        break;
    case 'W':
       title2 = "Madam";
        break;
    case ...etc.
}
printf("Dear %s %s and %s %s", title1, name1, title2, name2);

you can extract the switch to its own function for re-usability and compactness.

ratchet freak
  • 25,706
  • 2
  • 62
  • 97
18

Radical solution: Let the user specify their own title (from a predefined list that you provide).

Your solution (as viewed through English eyes) only appears to cater for Lords ("Sir") and ladies; most men would be addressed as "Mr", most women as either "Miss", "Mrs" or "Ms", depending on their marital status and personal opinions. Then there's a whole slew of other honorifics based on professional standings - "Doctors", "Professors", "Reverends" and even, if you're feeling really optimistic about your site, "Holiness"!

Simpler solution: You need a [single] function to translate "gender" into an honorific. Code it once and call it for both people:

printf("Dear %s %s and %s %s" 
   , getTitle( gender1 ), name1 
   , getTitle( gender2 ), name2 
   ) ; 
Phill W.
  • 11,891
  • 4
  • 21
  • 36
  • Problem here is: I do not have any control over the database whatsoever. but thanks for your additional information, appreciate it :) – moffeltje Jul 14 '15 at 12:34
  • 8
    `Dear Sir` as a form of address is perfectly acceptable for all males. I agree that as a _title_, Sir (as in `Sir Phill`) should be restricted to knights (not lords), but that's a different matter. – rojomoke Jul 14 '15 at 14:40
  • 1
    I don't see how this would require access to the database. This, to me, is the cleanest method of doing this. There are other nice switch reductions, but this is the cleanest replacement, as well as nicely modulizing the logic. – Dan Jul 14 '15 at 19:03
  • 4
    @rojomoke No, that isn't a different matter. This question is about "Dear Sir (insert name here)", not about a plain "Dear Sir". "Dear Sir (insert name here)" *is* using "Sir" as a title. – hvd Jul 14 '15 at 19:31
  • The BA frequent flyer signup page, maybe circa 2003, had "his holiness" in the drop-down list of titles. Still does for all I know. I remember because the drop-down was so long it crashed the portable browser we were integrating. I'd recommend a free field, except that BA in particular probably consults Debrett's and knows multiple forms of each title for different contexts (different envelope address and salutation as a minimum) – Steve Jessop Jul 15 '15 at 02:51
9

Titles really belong in the database, but you stated you have no control over this. You have not specified a language tag but the syntax is in the C family, so this will be pseudocode that is almost C++:

map<string, string> titles;
titles.emplace("M", "Sir");
titles.emplace("F", "Madam");

cout << "Dear " << titles[gender1] << " " << name1 << " and "
     << titles[gender2] << " " << name2 << endl;

The benefit to this is you bury the selection logic in a data structure rather than a code structure: this is similar to delegating to the database, and is more flexible. If you keep that map as a static constant somewhere, you can almost use it like a database: it becomes a single structure to update which can be used in many places in the code without needing to write more code.

  • 3
    Related reading: **[Why should a HashMap be used(in functions) to determine which value to return(for a key) when an if else construct can do the job in better time?](http://programmers.stackexchange.com/q/273523/22815)** –  Jul 14 '15 at 16:54
  • It might be a good idea to go with C++11 initializer syntax, and making it `static const`: `static const map titles{make_pair("M", "Sir"), make_pair("F", "Madam")};`. Well, one can leave the `const` out if modifying it should be allowed. – Deduplicator Jul 14 '15 at 17:44
  • @Deduplicator definitely, there is a better way. I was going for simplicity here given there is no language tag but it _looks_ like C++. But you are correct, assuming C++11. –  Jul 14 '15 at 17:46
3

ratchet freak's answer is quite a good idea if the sentences are all the same pattern, but with two insets, one each only dependent on gender1 respective gender2.

Phil W.'s answer is probably the most flexible answer as it allows explicit control over the greeting, though he's quite correct it's a radical change. You might not have the data in that form.

Kilian Foth's answer is probably the best for the question as asked, though he depends on switching on a string, which might not be possible or is likely more expensive at least.

A refinement on Kilian's answer is computing a single value from both inputs, and switching on that:

// Using a macro in C for readability. C++ would use a constexpr function
#define COMBINE(a, b) ((a<<CHAR_BIT)+b)

switch( COMBINE(gender1, gender2)) {
  case COMBINE('M', 'M'): 
    print "Dear Sirs";
    break;
  case COMBINE('M', 'F'): 
  case COMBINE('F', 'M'): 
    print "Dear Sir and Madam";
    break;
  ...
#undef COMBINE

Of course, as you are getting all four inputs (2 names and 2 genders) from a database, adding another table and joining on that to get the proper salutation is probably more flexible and maybe easier than the above.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
2

If your language allows you to do it, you can write

switch(gender1+gender2) {
  case "MM": 
    print "Dear Sirs";
    break;
  case "MF": 
  case "FM":
    print "Dear Sir and Madam";
    break;
  ...

It's not necessarily better than your version, since there's still duplication, but it does avoid the nested switch.

Kilian Foth
  • 107,706
  • 45
  • 295
  • 310
  • 5
    If you do this, for the love of cupcakes put this in an array or something and get rid of the switch.... salutation['MM'] = "Dear Sirs"; salutation['MF'] = "Dear Madam and Sir"; desiredSalutation = salutation[gender1 + gender2]; – JDT Jul 14 '15 at 09:20
  • 1
    @JDT [dictionary](http://programmers.stackexchange.com/a/145691/31260)? – gnat Jul 14 '15 at 09:24
  • What to call that exactly depends on the language, but basically a collection of keys and values, yes. – JDT Jul 14 '15 at 09:54
  • 1
    There's a slight refinement to that, which works in just about any language: Compute a single integer from both input-characters, and switch on that, not on a string. – Deduplicator Jul 14 '15 at 15:40
0

You would typically want UI strings like this to be pulled in from a string table instead of being hard-coded in the source code, for localization and ease of updating. So the approach I would take would be to use the inputs to build a lookup key, so something like:

var lookupKey = "SALUTATION_" + gender1 + "_" + gender2;
var format = GetLocalizedString(lookupKey);
printf(format, name1, name2);

The other suggestions about letting users select their own titles is valid, if you have the opportunity to get that information. I would still use a string table lookup in the solution.

bmm6o
  • 129
  • 2