¿Cómo reducir un cambio en una declaración de cambio?

9

Así que estoy haciendo un método para crear una línea de saludo basada en dos personas de una base de datos.

Hay cuatro parámetros: los dos nombres ( name1y name2) y los dos géneros ( gendery gender2).

Para cada combinación de género, tengo un tipo de salida diferente.

Por ejemplo: si el género 1 es M(hombre) y el género 2 también M, el resultado debería ser algo como:

Dear Sir name1 and Sir name2,

En este momento, mi interruptor se ve así:

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.
}

Tenga en cuenta que tengo varias opciones de género, como 'R'for "Dear Relation"y algunas más que no tengo tiempo para traducir.

¿Cómo puedo reducir esta declaración de doble interruptor?

Poner el segundo interruptor en un método no es una opción porque también hay un caso en el que ambos nombres son iguales y luego la salida debe combinarse como: "Dear Sir and Madame name1,"

moffeltje
fuente
1
Si su idioma lo permite, active una expresión que varía con ambos valores, por ejemplo gender1+gender2.
Kilian Foth
3
En un punto no relacionado, el título femenino para usar aquí es Madam, no Madame. Madamees la forma francesa
rojomoke
3
Ligeramente innecesario, pero el hecho de que su variable 'género' pueda ser 'masculino', 'femenino' o 'relación' es un poco inquietante ...
Paddy
44
"Tenga en cuenta que tengo varias opciones de género" Bueno, eso es sin duda en boga en estos días ...
Luminosidad carreras en órbita

Respuestas:

32

Agregue el título a los parámetros de 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);

puede extraer el interruptor a su propia función para volver a usarlo y ser compacto.

monstruo de trinquete
fuente
1
Eso a veces funciona, a veces no ...
Deduplicator
44
@Deduplicator Haga eso de forma predeterminada y maneje casos excepcionales por separado.
Val
17
... y hacer que sea una función genderToTitlepara que no tenga que repetirlo? (O use un bucle)
Bergi
18

Solución radical: deje que el usuario especifique su propio título (de una lista predefinida que proporcione).

Su solución (como se ve a través de los ojos ingleses) solo parece atender a los Lores ("Señor") y las damas; la mayoría de los hombres serían abordados como "Sr.", la mayoría de las mujeres como "Señorita", "Señora" o "Señora", dependiendo de su estado civil y sus opiniones personales. Luego hay una gran cantidad de otros honoríficos basados ​​en posiciones profesionales: "Médicos", "Profesores", "Reverendos" e incluso, si se siente realmente optimista sobre su sitio, ¡"Santidad"!

Solución más simple: necesita una función [única] para traducir "género" en honorífico. Codifíquelo una vez y llámelo para ambas personas:

printf("Dear %s %s and %s %s" 
   , getTitle( gender1 ), name1 
   , getTitle( gender2 ), name2 
   ) ; 
Phill W.
fuente
El problema aquí es: no tengo ningún control sobre la base de datos. pero gracias por su información adicional, lo agradezco :)
moffeltje
8
Dear Sircomo forma de domicilio es perfectamente aceptable para todos los hombres. Estoy de acuerdo en que, como título , Sir (como en Sir Phill) debería restringirse a los caballeros (no a los señores), pero ese es un asunto diferente.
rojomoke
1
No veo cómo esto requeriría acceso a la base de datos. Este, para mí, es el método más limpio para hacer esto. Hay otras reducciones de cambio agradables, pero este es el reemplazo más limpio, además de modular muy bien la lógica.
Dan
44
@rojomoke No, eso no es diferente. Esta pregunta es sobre "Estimado señor (inserte el nombre aquí)", no sobre un simple "Estimado señor". "Estimado señor (inserte el nombre aquí)" está usando "Sir" como título.
hvd
La página de registro de viajero frecuente de BA, quizás alrededor de 2003, tenía "su santidad" en la lista desplegable de títulos. Todavía lo hace por lo que sé. Lo recuerdo porque el menú desplegable fue tan largo que bloqueó el navegador portátil que estábamos integrando. Recomendaría un campo libre, excepto que BA en particular probablemente consulte a Debrett y conozca múltiples formas de cada título para diferentes contextos (diferentes direcciones de sobres y saludos como mínimo)
Steve Jessop
9

Los títulos realmente pertenecen a la base de datos, pero usted declaró que no tiene control sobre esto. No ha especificado una etiqueta de idioma, pero la sintaxis está en la familia C, por lo que será un seudocódigo que es casi C ++:

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

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

El beneficio de esto es que entierra la lógica de selección en una estructura de datos en lugar de una estructura de código: esto es similar a delegar en la base de datos y es más flexible. Si mantiene ese mapa como una constante estática en algún lugar, casi puede usarlo como una base de datos: se convierte en una estructura única para actualizar que se puede usar en muchos lugares del código sin necesidad de escribir más código.


fuente
Podría ser una buena idea ir con C ++ 11 inicializador de sintaxis, y lo que es static const: static const map<string, string> titles{make_pair("M", "Sir"), make_pair("F", "Madam")};. Bueno, uno puede constomitir si se permite modificarlo.
Deduplicador
@Deduplicator definitivamente, hay una mejor manera. Iba por simplicidad aquí dado que no hay una etiqueta de idioma pero parece C ++. Pero tienes razón, suponiendo que C ++ 11.
3

La respuesta de Ratchet Freak es una buena idea si las oraciones son todas del mismo patrón, pero con dos inserciones, una de las cuales solo depende de gender1cada una gender2.

La respuesta de Phil W. es probablemente la respuesta más flexible, ya que permite un control explícito sobre el saludo, aunque es bastante correcto, es un cambio radical. Es posible que no tenga los datos de esa forma.

La respuesta de Kilian Foth es probablemente la mejor para la pregunta formulada, aunque depende de encender una cadena, lo que podría no ser posible o al menos es más costoso.

Un refinamiento en la respuesta de Kilian es calcular un valor único de ambas entradas y activar eso:

// 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

Por supuesto, como está obteniendo las cuatro entradas (2 nombres y 2 géneros) de una base de datos, agregar otra tabla y unirse para obtener el saludo adecuado es probablemente más flexible y quizás más fácil que el anterior.

Deduplicador
fuente
2

Si su idioma le permite hacerlo, puede escribir

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

No es necesariamente mejor que su versión, ya que todavía hay duplicación, pero evita el anidado switch.

Kilian Foth
fuente
55
Si hace esto, por amor a los cupcakes, ponga esto en una matriz o algo así y deshágase del interruptor ... salutation ['MM'] = "Estimados señores"; salutation ['MF'] = "Estimada señora y señor"; Saludo deseado = saludo [género1 + género2];
JDT
1
@JDT diccionario ?
mosquito
Cómo llamar exactamente eso depende del idioma, pero básicamente una colección de claves y valores, sí.
JDT
1
Hay un ligero refinamiento de eso, que funciona en casi cualquier idioma: calcule un solo entero a partir de ambos caracteres de entrada y actívelo, no en una cadena.
Deduplicador
0

Por lo general, desearía que las cadenas de interfaz de usuario como esta se extraigan de una tabla de cadenas en lugar de estar codificadas en el código fuente, para su localización y facilidad de actualización. Entonces, el enfoque que tomaría sería usar las entradas para construir una clave de búsqueda, así que algo como:

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

Las otras sugerencias sobre permitir que los usuarios seleccionen sus propios títulos son válidas, si tiene la oportunidad de obtener esa información. Todavía usaría una búsqueda de tabla de cadenas en la solución.

bmm6o
fuente