Comment puis-je améliorer et raccourcir ce bloc de code? [fermé]

9

Cette fonction prend une chaîne d'ADN telle que «GTCA» et renvoie un tableau contenant des paires d'ADN correctement appariées.

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

C'est correct. Cependant, j'essaie de trouver un moyen plus court et plus simple de l'écrire. Quelqu'un peut-il m'aider avec ce que je devrais utiliser?

CocoFlade
la source
1
utiliser facilement cette méthode dna [i] .toLowerCase ()
Thaier Alkhateeb
9
Si votre code fonctionne et que vous souhaitez simplement des améliorations, essayez codereview.stackexchange.com
Peter Collingridge
Je ne pense pas que ce code fonctionne comme prévu, | ne fait pas logique OU en Javascript comme||
Ma'moun othman
2
@mamounothman - C'est vrai, mais les deux fonctionneront dans ce code (ce ||serait mieux, cependant).
TJ Crowder

Réponses:

14

Vous pouvez améliorer votre code en suivant les étapes suivantes:

  • Lorsqu'il existe plusieurs instructions if et toutes ont la même structure, vous devez probablement utiliser un objet
  • Vous devez vérifier les majuscules et les minuscules. Utilisez simplement toLowerCase()en entrée.
  • Vous pouvez splitla chaîne et map()plutôt que de créer des push()valeurs de tableau en elle.

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

}

Si la chaîne peut contenir autre chose que les lettres spécifiques, alors vous devez filter()les undefinedvaleurs aprèsmap

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

Une autre meilleure est mentionnée par @RobG dans les commentaires que nous pouvons supprimer les lettres indésirables de la chaîne avant de la parcourir.

return dna
        .toLowerCase()
        .replace(/[^cgta]/g,'')
        .split('')
        .map(x => obj[x])
Maheer Ali
la source
1
Si l'adn contient un caractère non répertorié, vous aurez des undefinedvaleurs dans votre tableau final.
Grégory NEUT
1
@ GrégoryNEUT Ajout d'un correctif pour ce cas dans ma réponse
Maheer Ali
Ou vous pouvez prétraiter la chaîne avec dna.toLowerCase().replace(/[^cgta]/g,'').... ;-)
RobG
@RobG Vraiment aimé ça. Je l'ai ajouté à ma réponse.
Maheer Ali
1
J'ai raté que c'était une chaîne. :-) FWIW, un moyen plus convivial Unicode de diviser les chaînes en tableaux est maintenant [...dna]. Il ne casse pas les paires de substitution. (Ou Array.from, ce qui est particulièrement utile si vous allez cartographier:. Array.from(dna, mappingFunction)) (Pas tout ce qui est pertinent ici, je suppose dnaque ne contient quec , g, tet a.)
TJ Crowder
3

J'aurais probablement:

  1. Utiliser une for-ofboucle (ou éventuellement un mappage avec un filtrage possible)

  2. Utiliser un objet de recherche ou une carte

  3. Faites en sorte que la chaîne soit en minuscule ou en majuscule lors de la commutation / recherche (mais les entrées dupliquées dans le commutateur / la recherche fonctionnent également):

Si tu le sais dna ne contiendra que c/ C, g/ G, t/ T/ ou a/ A(ce qui, si je comprends bien, est vrai de l'ADN ;-)), alors vous pouvez l'utiliser Array.fromavec sa fonction de mappage avec un objet de recherche / Map:

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

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

J'utilise Array.fromparce qu'il divisera la chaîne sur les points de code , pas seulement les unités de code (ne rompt pas les paires de substitution) et possède une fonction de mappage si vous fournissez une fonction de mappage. (Fondamentalement, Array.from(str, mappingFunction)est[...str].map(mappingFunction) sans le tableau intermédiaire.) Probablement pas tout ce qui est pertinent ici étant donné le contenu de votre chaîne, mais cela peut avoir de l'importance si votre chaîne peut contenir des paires de substitution.

Ou avec 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 vous ne pouvez pas faire cette hypothèse, ajoutez .filterpour filtrer ceux qui ne correspondent pas:

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);
}

Ou si vous voulez éviter de créer le tableau supplémentaire que le filtercréerait, restez avecfor-of (ou même votre 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
la source
2

Vous pouvez utiliser un mappage de recherche pour simplifier la boucle:

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;
}
Pointu
la source
C'est intéressant, je n'ai pas pensé à le faire de cette façon, merci!
CocoFlade
2

Peut-être pas raccourci mais certainement plus maintenable.

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;
  }, []);
}

Vous pourriez également faire:

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
la source
2

Vous pouvez essayer d'utiliser un switch caseet un forEachfuncion, comme ceci:

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
la source
1

Vous pouvez minuscule la chaîne qui vous permettra de supprimer la vérification de la chaîne majuscule:

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
la source
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
la source