Jak mogę ulepszyć i skrócić ten blok kodu? [Zamknięte]

9

Ta funkcja pobiera ciąg DNA, taki jak „GTCA” i zwraca tablicę zawierającą odpowiednio dopasowane pary DNA.

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

To jest poprawne. Próbuję jednak znaleźć krótszy, prostszy sposób na napisanie tego. Czy ktoś może mi pomóc z tym, czego powinienem używać?

CocoFlade
źródło
1
użyj łatwo tej metody dna [i] .toLowerCase ()
Thaier Alkhateeb
9
Jeśli Twój kod działa, a potrzebujesz tylko ulepszeń, spróbuj codereview.stackexchange.com
Peter Collingridge
Nie sądzę, że ten kod działa zgodnie z przeznaczeniem, | nie robi logicznego LUB w JavaScript, jak||
ROOT
2
@mamounothman - To prawda, ale oba będą działać w tym kodzie ( ||byłoby jednak lepiej).
TJ Crowder

Odpowiedzi:

14

Możesz poprawić swój kod, wykonując następujące czynności:

  • Gdy istnieje wiele instrukcji if i wszystkie mają tę samą strukturę, prawdopodobnie musisz użyć obiektu
  • Musisz zaznaczyć zarówno wielkie, jak i małe litery. Po prostu użyj toLowerCase()na wejściu.
  • Możesz splitciąg i map()to zamiast tworzyć w nim push()wartości tablicowe .

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

}

Jeśli ciąg może zawierać cokolwiek innego niż określone litery, musisz filter()wprowadzić undefinedwartości pomap

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

Kolejna lepsza rzecz jest wspomniana przez @RobG w komentarzach, że możemy usunąć niechciane litery z łańcucha przed zapętleniem go.

return dna
        .toLowerCase()
        .replace(/[^cgta]/g,'')
        .split('')
        .map(x => obj[x])
Maheer Ali
źródło
1
Jeśli dna zawiera niewymieniony znak, będziesz mieć undefinedwartości w końcowej tablicy.
Grégory NEUT
1
@ GrégoryNEUT Dodałem poprawkę do tej sprawy w mojej odpowiedzi
Maheer Ali
Lub możesz wstępnie przetworzyć ciąg za pomocą dna.toLowerCase().replace(/[^cgta]/g,'').... ;-)
RobG
@RobG Naprawdę to lubiłem. Dodałem to, moja odpowiedź.
Maheer Ali
1
Tęskniłem za tym, że to sznurek. :-) FWIW, teraz jest bardziej przyjazny dla Unicode sposób dzielenia łańcuchów na tablice [...dna]. Nie rozkłada par surogatów. (Lub Array.from, co jest szczególnie przydatne, jeśli masz zamiar map: Array.from(dna, mappingFunction)). (Nie wszystko, co istotne tutaj, zakładam dnazawiera tylko c, g, t, i a.)
TJ Crowder
3

Prawdopodobnie:

  1. Użyj for-ofpętli (lub ewentualnie mapowania z możliwym filtrowaniem)

  2. Użyj obiektu wyszukiwania lub mapy

  3. Ustaw ciąg jako małe lub wielkie litery podczas przełączania / wyszukiwania (ale działają również zduplikowane wpisy w przełączniku / wyszukiwaniu):

Jeśli wiesz, że zawsze dnabędzie zawierał c/ C, g/ G, t/ T/ lub a/ A(co, jak rozumiem, dotyczy DNA ;-)), możesz użyć Array.fromjego funkcji mapowania z obiektem wyszukiwania / Mapą:

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

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

Używam, Array.fromponieważ podzieli ciąg na punkty kodowe , nie tylko jednostki kodowe (nie rozbija par zastępczych) i ma funkcję mapowania, jeśli udostępnisz funkcję mapowania. (Zasadniczo Array.from(str, mappingFunction)jest, [...str].map(mappingFunction)ale bez pośredniej tablicy). Prawdopodobnie nie wszystko, co jest istotne, biorąc pod uwagę zawartość łańcucha, ale może mieć znaczenie, jeśli łańcuch może zawierać pary zastępcze.

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

Jeśli nie możesz przyjąć tego założenia, dodaj, .filteraby odfiltrować te, które nie pasowały:

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

Lub jeśli chcesz uniknąć tworzenia dodatkowej tablicy, którą filterby utworzył, trzymaj się for-of(lub nawet swojej 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
źródło
2

Aby uprościć pętlę, możesz użyć odwzorowania wyszukiwania:

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;
}
Pointy
źródło
To ciekawe, że nie pomyślałem o zrobieniu tego w ten sposób, dziękuję!
CocoFlade
2

Może nie skrócony, ale zdecydowanie łatwiejszy w utrzymaniu.

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

Możesz także:

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
źródło
2

Możesz spróbować użyć a switch casei forEachfuncion, takich jak to:

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
źródło
1

Możesz wpisać małe litery, które pozwolą ci usunąć sprawdzanie łańcucha:

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
źródło
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
źródło