Come posso migliorare e abbreviare questo blocco di codice? [chiuso]


9

Questa funzione prende una stringa di DNA come 'GTCA' e restituisce un array contenente coppie di DNA correttamente abbinate.

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

Questo è corretto. Comunque sto cercando di trovare un modo più breve e semplice di scriverlo. Qualcuno può aiutarmi con quello che dovrei usare?


1
usa facilmente questo metodo dna [i] .toLowerCase ()
Thaier Alkhateeb

9
Se il tuo codice funziona e vuoi solo miglioramenti, prova codereview.stackexchange.com
Peter Collingridge,

Non penso che questo codice funzioni come previsto, | non funziona in modo logico O in Javascript come||
Ma'moun othman

2
@mamounothman - È vero, ma entrambi funzioneranno con quel codice ( ||sarebbe meglio, però).
TJ Crowder,

Risposte:


14

Puoi migliorare il tuo codice nei seguenti passaggi:

  • Quando sono presenti più istruzioni if ​​e tutte hanno la stessa struttura, è probabilmente necessario utilizzare un oggetto
  • È necessario controllare sia maiuscole che minuscole. Basta usare toLowerCase()sull'input.
  • È possibile utilizzare splitla stringa e la map()stessa anziché creare push()in essa valori di array .

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

}

Se la stringa potrebbe contenere qualcosa di diverso dalle lettere specifiche, allora è necessario filter()i undefinedvalori dopomap

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

Un altro aspetto migliore è menzionato da @RobG nei commenti che possiamo rimuovere le lettere indesiderate dalla stringa prima di attraversarla.

return dna
        .toLowerCase()
        .replace(/[^cgta]/g,'')
        .split('')
        .map(x => obj[x])

1
Se il dna contiene un carattere non elencato, avrai undefinedvalori nel tuo array finale.
Grégory NEUT,

1
@ GrégoryNEUT Aggiunta una correzione per quel caso nella mia risposta
Maheer Ali,

Oppure puoi pre-elaborare la stringa con dna.toLowerCase().replace(/[^cgta]/g,'').... ;-)
RobG

@RobG Mi è davvero piaciuto. L'ho aggiunta alla mia risposta.
Maheer Ali,

1
Mi mancava che fosse una stringa. :-) FWIW, ora è un modo più semplice per Unicode di dividere le stringhe in array [...dna]. Non rompe le coppie surrogate. (O Array.from, il che è particolarmente utile se si sta andando a mappare: Array.from(dna, mappingFunction).) (Non tutto ciò che qui interessa, presumo dnacontiene solo c, g, t, e a.)
TJ Crowder

3

Probabilmente avrei:

  1. Usa un for-ofloop (o eventualmente mappando con un possibile filtro)

  2. Usa un oggetto di ricerca o Mappa

  3. Rendi la stringa minuscola o maiuscola quando cambi / cerca (ma funzionano anche le voci duplicate nel cambio / ricerca):

Se sai che dnaconterrà sempre c/ C, g/ G, t/ T/ o a/ A(che, a quanto ho capito, è vero per il DNA ;-)), puoi usare la Array.fromsua funzione di mappatura con un oggetto di ricerca / Mappa:

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

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

Sto usando Array.fromperché dividerà la stringa su punti di codice , non solo unità di codice (non spezza le coppie surrogate) e ha una funzione di mappatura se si fornisce una funzione di mappatura. (Fondamentalmente, Array.from(str, mappingFunction)è [...str].map(mappingFunction)ma senza l'array intermedio.) Probabilmente non tutto ciò che è rilevante qui dato il contenuto della stringa, ma può importare se la stringa può contenere coppie surrogate.

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

Se non riesci a fare questo presupposto, aggiungi .filterper filtrare quelli che non avevano una corrispondenza:

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 se vuoi evitare di creare l'array aggiuntivo filterche creerebbe, mantieni for-of(o anche il tuo 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;
}

2

È possibile utilizzare un mapping di ricerca per semplificare il 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;
}

È interessante, non ho pensato di farlo in questo modo, grazie!
CocoFlade,

2

Forse non abbreviato ma sicuramente più mantenibile.

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

Puoi anche fare:

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

2

Puoi provare a usare a switch casee una forEachfunzione, in questo modo:

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

1

Puoi mettere in minuscolo la stringa che ti permetterà di rimuovere il controllo della stringa maiuscola:

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

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;

}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.