Como posso melhorar e diminuir esse bloco de código? [fechadas]

9

Essa função pega uma sequência de DNA como 'GTCA' e retorna uma matriz contendo pares de DNA correspondidos corretamente.

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

Isto está correto. No entanto, estou tentando encontrar uma maneira mais curta e simples de escrevê-lo. Alguém pode me ajudar com o que devo usar?

CocoFlade
fonte
11
use facilmente esse método dna [i] .toLowerCase ()
Thaier Alkhateeb
9
Se o seu código funcionar e você quiser apenas melhorias, tente codereview.stackexchange.com
Peter Collingridge
Eu não acho que esse código funcione como pretendido, | não faça OR lógico em Javascript como||
Ma'moun othman 11/02
2
@mamounothman - Isso é verdade, mas ambos funcionarão nesse código ( ||seria melhor, no entanto).
TJ Crowder

Respostas:

14

Você pode melhorar seu código nas seguintes etapas:

  • Quando houver várias instruções if e todas tiverem a mesma estrutura, você provavelmente precisará usar um objeto
  • Você precisa verificar maiúsculas e minúsculas. Basta usar toLowerCase()na entrada.
  • Você pode splita string e map()ela, em vez de criar push()valores de matriz nela.

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

}

Se a string puder conter qualquer outra letra específica, você precisará filter()dos undefinedvalores apósmap

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

Outra melhoria é mencionada pelo @RobG nos comentários: podemos remover as letras indesejadas da string antes de passar por ela.

return dna
        .toLowerCase()
        .replace(/[^cgta]/g,'')
        .split('')
        .map(x => obj[x])
Maheer Ali
fonte
11
Se o dna contiver um caractere não listado, você terá undefinedvalores em sua matriz final.
Grégory NEUT
11
@ GrégoryNEUT Adicionada uma correção para esse caso na minha resposta
Maheer Ali 11/02
Ou você pode pré-processar a string com dna.toLowerCase().replace(/[^cgta]/g,'').... ;-)
RobG 11/02
@RobG Realmente gostei disso. Eu adicionei a minha resposta.
Maheer Ali
11
Perdi que fosse uma corda. :-) FWIW, uma maneira mais amigável para Unicode de dividir strings em matrizes agora é [...dna]. Não quebra pares substitutos. (Ou Array.from, o que é particularmente útil se você estiver indo para mapear: Array.from(dna, mappingFunction).) (Não tão relevante aqui, eu assumo dnacontém apenas c, g, t, e a.)
TJ Crowder
3

Eu provavelmente:

  1. Use um for-ofloop (ou possivelmente mapeando com possível filtragem)

  2. Use um objeto de pesquisa ou mapa

  3. Coloque a string em minúscula ou maiúscula ao alternar / procurar (mas entradas duplicadas na alternância / pesquisa também funcionam):

Se você sabe que dnasó vai conter c/ C, g/ G, t/ T/ ou a/ A(que, como eu a entendo, é verdade de DNA ;-)), então você pode usar Array.fromcom o seu recurso de mapeamento com um objeto de pesquisa / Mapa:

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

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

Estou usando Array.fromporque ele dividirá a string em pontos de código , não apenas em unidades de código (não divide os pares substitutos) e possui um recurso de mapeamento se você fornecer uma função de mapeamento. (Basicamente, Array.from(str, mappingFunction)é [...str].map(mappingFunction)mas sem a matriz intermediária.) Provavelmente nem tudo é relevante aqui, considerando o conteúdo da sua string, mas pode importar se ela pode conter pares substitutos.

Ou com um 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 você não pode fazer essa suposição, adicione .filterpara filtrar as que não corresponderam:

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, se você deseja evitar a criação de uma matriz extra, a mesma filterseria criada for-of(ou mesmo a sua 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
fonte
2

Você pode usar um mapeamento de pesquisa para simplificar o loop:

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;
}
Pontudo
fonte
Isso é interessante, eu não pensei em fazer dessa maneira, obrigado!
CocoFlade
2

Talvez não seja reduzido, mas definitivamente mais sustentável.

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

Você também pode fazer:

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

Você pode tentar usar ae switch caseuma forEachfunção, assim:

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

Você pode minúscula a string que permitirá remover a verificação da string capital:

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