Wie kann ich diesen Codeblock verbessern und verkürzen? [geschlossen]

9

Diese Funktion verwendet eine DNA-Zeichenfolge wie 'GTCA' und gibt ein Array zurück, das korrekt übereinstimmende DNA-Paare enthält.

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

Das ist richtig. Ich versuche jedoch, eine kürzere, einfachere Art zu finden, es zu schreiben. Kann mir jemand helfen, was ich verwenden soll?

CocoFlade
quelle
1
Verwenden Sie einfach diese Methode dna [i] .toLowerCase ()
Thaier Alkhateeb
9
Wenn Ihr Code funktioniert und Sie nur Verbesserungen wünschen, versuchen Sie es mit codereview.stackexchange.com
Peter Collingridge
Ich denke nicht, dass dieser Code wie beabsichtigt | funktioniert, kein logisches ODER in Javascript wie||
Ma'moun othman
2
@mamounothman - Das stimmt, aber beide funktionieren in diesem Code ( ||wäre aber besser).
TJ Crowder

Antworten:

14

Sie können Ihren Code in folgenden Schritten verbessern:

  • Wenn es mehrere if-Anweisungen gibt und alle dieselbe Struktur haben, müssen Sie wahrscheinlich ein Objekt verwenden
  • Sie müssen sowohl Groß- als auch Kleinbuchstaben überprüfen. Einfach toLowerCase()bei der Eingabe verwenden.
  • Sie können splitdie Zeichenfolge und map()es, anstatt Array- push()Werte darin zu erstellen .

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

}

Wenn die Zeichenfolge andere spezifische Buchstaben enthalten könnte, müssen Sie filter()die folgenden undefinedWerte eingebenmap

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

Ein weiteres besseres wird von @RobG in den Kommentaren erwähnt, dass wir die unerwünschten Buchstaben aus der Zeichenfolge entfernen können, bevor wir sie durchlaufen.

return dna
        .toLowerCase()
        .replace(/[^cgta]/g,'')
        .split('')
        .map(x => obj[x])
Maheer Ali
quelle
1
Wenn dna ein nicht aufgeführtes Zeichen enthält, enthält undefinedIhr endgültiges Array Werte.
Grégory NEUT
1
@ GrégoryNEUT In meiner Antwort wurde ein Fix für diesen Fall
hinzugefügt
Oder Sie können den String mit vorverarbeiten dna.toLowerCase().replace(/[^cgta]/g,'').... ;-)
RobG
@RobG Hat mir sehr gut gefallen. Ich habe es meiner Antwort hinzugefügt.
Maheer Ali
1
Ich habe vermisst, dass es eine Schnur war. :-) FWIW, eine Unicode-freundlichere Möglichkeit, Strings in Arrays aufzuteilen, ist jetzt [...dna]. Es werden keine Ersatzpaare aufgelöst. (Oder Array.from, was besonders nützlich ist , wenn Sie zur Karte gehen: Array.from(dna, mappingFunction).) (Nicht alles , was relevant hier gehe ich davon dnanur enthält c, g, t, und a.)
TJ Crowder
3

Ich würde wahrscheinlich:

  1. Verwenden Sie eine for-ofSchleife (oder möglicherweise eine Zuordnung mit möglicher Filterung).

  2. Verwenden Sie ein Suchobjekt oder eine Karte

  3. Machen Sie die Zeichenfolge beim Wechseln / Nachschlagen in Klein- oder Großbuchstaben (aber doppelte Einträge in der Umschaltung / Suche funktionieren auch):

Wenn Sie wissen, dass dies dnaimmer nur c/ C, g/ G, t/ T/ oder a/ enthält A(was meines Wissens für DNA gilt ;-)), können Sie die Array.fromZuordnungsfunktion mit einem Suchobjekt / Map verwenden:

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

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

Ich verwende es, Array.fromweil es die Zeichenfolge auf Codepunkte aufteilt , nicht nur auf Codeeinheiten (löst keine Ersatzpaare auf) und eine Zuordnungsfunktion hat, wenn Sie eine Zuordnungsfunktion bereitstellen. (Grundsätzlich Array.from(str, mappingFunction)ist es [...str].map(mappingFunction)aber ohne das Zwischenarray.) Wahrscheinlich nicht alles, was hier angesichts des Inhalts Ihrer Zeichenfolge relevant ist, aber es kann wichtig sein, ob Ihre Zeichenfolge Ersatzpaare enthält.

Oder mit einem 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()));
}                                                                                                                           

Wenn Sie diese Annahme nicht treffen können, fügen Sie hinzu .filter, um diejenigen herauszufiltern, die keine Übereinstimmung hatten:

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

Oder wenn Sie vermeiden möchten, das zusätzliche Array filterzu erstellen, das erstellt wird, bleiben Sie bei for-of(oder sogar Ihrem 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
quelle
2

Sie können eine Lookup-Zuordnung verwenden, um die Schleife zu vereinfachen:

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;
}
Spitze
quelle
Das ist interessant, ich habe nicht daran gedacht, es so zu machen, danke!
CocoFlade
2

Vielleicht nicht verkürzt, aber definitiv wartbarer.

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

Sie könnten auch tun:

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
quelle
2

Sie könnten versuchen, eine switch caseund eine forEachFunktion wie folgt zu verwenden:

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
quelle
1

Sie können die Zeichenfolge in Kleinbuchstaben schreiben, um die Prüfung der Großbuchstabenzeichenfolge zu entfernen:

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