¿Cómo puedo mejorar y acortar este bloque de código? [cerrado]

9

Esta función toma una cadena de ADN como 'GTCA' y devuelve una matriz que contiene pares de ADN coincidentes correctamente.

function pairDNA(dna) {

  const pairs = []

  for (let i = 0; i < dna.length; i ++) {

    if (dna[i] === "C" | dna[i] === "c") {
      pairs.push("CG");
    } else if (dna[i] === "G"| dna[i] === "g") {
      pairs.push("GC");
    } else if (dna[i] === "T"| dna[i] === "t") {
    pairs.push("TA");
    } else if (dna[i] === "A"| dna[i] === "a") {
      pairs.push("AT");
    }
  }

return pairs;
}

Esto es correcto. Sin embargo, estoy tratando de encontrar una forma más corta y simple de escribirlo. ¿Alguien puede ayudarme con lo que debería estar usando?

CocoFlade
fuente
1
use fácilmente este método dna [i] .toLowerCase ()
Thaier Alkhateeb
99
Si su código funciona y solo desea mejoras, intente codereview.stackexchange.com
Peter Collingridge
No creo que este código funcione según lo previsto, | no hace lógica O en Javascript como||
Ma'moun othman
2
@mamounothman: eso es cierto, pero ambos funcionarán en ese código ( ||aunque sería mejor).
TJ Crowder

Respuestas:

14

Puede mejorar su código en los siguientes pasos:

  • Cuando hay múltiples sentencias if y todas tienen la misma estructura, probablemente necesite usar un objeto
  • Debe verificar mayúsculas y minúsculas. Solo use toLowerCase()en la entrada.
  • Puede splitla cadena y map()en lugar de crear una matriz de push()valores en ella.

function pairDNA(dna) {
  const obj = {
    c: 'CG',
    g: 'GC',
    t: 'TA',
    a: "AT"
  }
  return dna.split('').map(x => obj[x.toLowerCase()])

}

Si la cadena puede contener algo más que las letras específicas, entonces necesita filter()los undefinedvalores después demap

return dna.split('').map(x => obj[x.toLowerCase()]).filter(x => x !== undefined)

@RobG menciona otra mejor en los comentarios de que podemos eliminar las letras no deseadas de la cadena antes de recorrerla.

return dna
        .toLowerCase()
        .replace(/[^cgta]/g,'')
        .split('')
        .map(x => obj[x])
Maheer Ali
fuente
1
Si el ADN contiene un carácter no listado, tendrá undefinedvalores en su matriz final.
Grégory NEUT
1
@ GrégoryNEUT Agregó una solución para ese caso en mi respuesta
Maheer Ali
O puede preprocesar la cadena con dna.toLowerCase().replace(/[^cgta]/g,'').... ;-)
RobG
@RobG Realmente me gustó eso. Lo agregué a mi respuesta.
Maheer Ali
1
Extrañé que fuera una cuerda. :-) FWIW, ahora es una forma más amigable de Unicode de dividir cadenas en matrices [...dna]. No rompe pares sustitutos. (O Array.from, lo que es particularmente útil si se va a asignar: Array.from(dna, mappingFunction).) (No todo lo que aquí interesa, que supongo que dnasolamente contiene c, g, t, y a.)
TJ Crowder
3

Yo probablemente:

  1. Use un for-ofbucle (o posiblemente un mapeo con posible filtrado)

  2. Use un objeto de búsqueda o un mapa

  3. Haga que la cadena sea minúscula o mayúscula al cambiar / mirar hacia arriba (pero las entradas duplicadas en el cambio / búsqueda también funcionan):

Si sabe que dnasolo contendrá c/ C, g/ G, t/ T/ o a/ A(que, según tengo entendido, es cierto para el ADN ;-)), puede usarlo Array.fromcon su función de mapeo con un objeto de búsqueda / Mapa:

const table = {
    c: "CG",
    g: "GC",
    t: "TA",
    a: "AT"
};

function pairDNA(dna) {
  return Array.from(dna, entry => table[entry.toLowerCase()]);
}                                                                                                                           

Estoy usando Array.fromporque dividirá la cadena en los puntos de código , no solo las unidades de código (no divide los pares sustitutos) y tiene una función de mapeo si proporciona una función de mapeo. (Básicamente, Array.from(str, mappingFunction)es [...str].map(mappingFunction)pero sin la matriz intermedia.) Probablemente no sea tan relevante aquí dado el contenido de su cadena, pero puede importar si su cadena puede contener pares sustitutos.

O con un Map:

const table = new Map([
  [c, "CG"],
  [g, "GC"],
  [t, "TA"],
  [a, "AT"]
]);

function pairDNA(dna) {
  return Array.from(dna, entry => table.get(entry.toLowerCase()));
}                                                                                                                           

Si no puede hacer esa suposición, agregue .filterpara filtrar los que no coinciden:

function pairDNA(dna) {
  return Array.from(dna, entry => table.get(entry.toLowerCase())).filter(Boolean);
  // or if using an object: return dna.map(entry => table[entry.toLowerCase()]).filter(Boolean);
}

O si desea evitar crear la matriz adicional filterque crearía, quédese con for-of(o incluso su for):

const table = {
    c: "CG",
    g: "GC",
    t: "TA",
    a: "AT"
};

function pairDNA(dna) {
  const pairs = [];

  for (const entry of dna) {
    const value = table[entry.toLowerCase()];
    if (value) {
      pairs.push(value);
    }
  }
  return pairs;
}
TJ Crowder
fuente
2

Puede usar una asignación de búsqueda para simplificar el ciclo:

function pairDNA(dna) {

  const pairs = [], key = { G: "GC", C: "CG", A: "AT", T: "TA" };

  for (let i = 0; i < dna.length; i ++)
    pairs.push(key[dna[i].toUpperCase()]);
  return pairs;
}
Puntiagudo
fuente
Eso es interesante. No pensé en hacerlo de esta manera, ¡gracias!
CocoFlade
2

Quizás no acortado pero definitivamente más fácil de mantener.

function pairDNA(dna) {
  const map = {
    C: 'CG',
    c: 'CG',
    G: 'GC',
    g: 'GC',
    T: 'TA',
    t: 'TA',
    A: 'AT',
    a: 'AT',
  };

  return dna.split('').reduce((tmp, x) => {
    if (map[x]) {
      tmp.push(map[x]);
    }

    return tmp;
  }, []);
}

También puedes hacer:

function pairDNA(dna) {
  const map = {
    c: 'CG',
    g: 'GC',
    t: 'TA',
    a: 'AT',
  };

  return dna.split('').reduce((tmp, x) => {
    if (map[x].toLowerCase()) {
      tmp.push(map[x]);
    }

    return tmp;
  }, []);
}
Grégory NEUT
fuente
2

Podría intentar usar ay switch caseuna función forEach, como esta:

function pairDNA(dna) {
  let pairs = [];

  dna.forEach( dnaValue => {
    switch (dnaValue.toLowerCase()) {
      case "c":
        pairs.push("CG");
        break;
      case "g":
        pairs.push("GC");
        break;
      case "t":
        pairs.push("TA");
        break;
      case "a":
        pairs.push("AT");
        break;
    }
  })

  return pairs;
}
CH4B
fuente
1

Puede poner en minúscula la cadena que le permitirá eliminar la comprobación de la cadena de mayúsculas:

function pairDNA(dna) {
  dna = dna.toLowerCase();
  const pairs = []
  for (let i = 0; i < dna.length; i ++) {
   if (dna[i]=== "c") {
     pairs.push("CG");
   } else if (dna[i]dna[i] === "g") {
     pairs.push("GC");
   } else if (dna[i] === "t") {
     pairs.push("TA");
   } else if (dna[i] === "a") {
     pairs.push("AT");
   }
 }

 return p;
}
Mamun
fuente
1
const lookup = {
    c: "CG", 
    g: "GC", 
    t: "TA", 
    a: "AT"
};

function pairDNA(dna) {  

  const pairs = [];

  for (let i = 0; i < dna.length; i ++) {
     pairs.push( lookup[dna[i].toLowerCase()] );
  }

  return pairs;

}
James
fuente