Bagaimana saya bisa meningkatkan dan mempersingkat blok kode ini? [Tutup]

9

Fungsi ini mengambil string DNA seperti 'GTCA' dan mengembalikan array yang berisi pasangan DNA yang cocok dengan benar.

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

Ini benar. Namun saya mencoba mencari cara yang lebih pendek, lebih sederhana untuk menulisnya. Adakah yang bisa membantu saya dengan apa yang seharusnya saya gunakan?

CocoFlade
sumber
1
gunakan metode ini dengan mudah dna [i] .toLowerCase ()
Thaier Alkhateeb
9
Jika kode Anda berfungsi dan Anda hanya menginginkan peningkatan, coba codereview.stackexchange.com
Peter Collingridge
Saya tidak berpikir kode ini berfungsi sebagaimana dimaksud, | tidak melakukan logika ATAU dalam Javascript seperti||
Ma'moun othman
2
@amounothman - Itu benar, tetapi keduanya akan bekerja dalam kode itu ( ||akan lebih baik, meskipun).
TJ Crowder

Jawaban:

14

Anda dapat meningkatkan kode Anda dalam langkah-langkah berikut:

  • Ketika ada beberapa pernyataan if dan semuanya memiliki struktur yang sama, Anda mungkin perlu menggunakan objek
  • Anda perlu memeriksa huruf besar dan kecil. Gunakan sajatoLowerCase() pada input.
  • Anda dapat splitmenggunakan string dan map()alih-alih menciptakan push()nilai array ke dalamnya.

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

}

Jika string bisa berisi apa pun selain huruf-huruf tertentu maka Anda perlu filter() yang undefinednilai setelahmap

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

Lain yang lebih baik disebutkan oleh @RobG di komentar bahwa kita dapat menghapus surat yang tidak diinginkan dari string sebelum mengulanginya.

return dna
        .toLowerCase()
        .replace(/[^cgta]/g,'')
        .split('')
        .map(x => obj[x])
Maheer Ali
sumber
1
Jika dna berisi karakter yang tidak terdaftar, Anda akan memiliki undefinednilai dalam array akhir Anda.
Grégory NEUT
1
@ GrégoryNEUT Menambahkan perbaikan untuk kasus itu dalam jawaban saya
Maheer Ali
Atau Anda dapat melakukan pra-proses string dna.toLowerCase().replace(/[^cgta]/g,'').... ;-)
RobG
@RobG Sangat menyukai itu. Saya menambahkannya ke jawaban saya.
Maheer Ali
1
Saya merindukan itu adalah string. :-) FWIW, cara yang lebih ramah-Unicode untuk memecah string menjadi array sekarang adalah [...dna]. Itu tidak memecah pasangan pengganti. (Atau Array.from, yang sangat berguna jika Anda akan untuk memetakan: Array.from(dna, mappingFunction).) (Tidak semua yang relevan di sini, saya asumsikan dnahanya berisi c, g, t, dan a.)
TJ Crowder
3

Saya mungkin akan:

  1. Gunakan for-ofperulangan (atau mungkin pemetaan dengan kemungkinan penyaringan)

  2. Gunakan objek pencarian atau Peta

  3. Jadikan string huruf besar atau kecil saat beralih / melihat ke atas (tetapi entri yang digandakan dalam sakelar / pencarian juga berfungsi):

Jika Anda tahu bahwa dnahanya akan berisi c/ C, g/ G, t/ T/, atau a/ A(yang, seperti yang saya pahami, adalah benar dari DNA ;-)), maka Anda dapat menggunakan Array.fromfitur pemetaannya dengan objek pencarian / Peta:

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

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

Saya menggunakan Array.fromkarena akan membagi string pada poin kode , bukan hanya unit kode (tidak memecah pasangan pengganti) dan memiliki fitur pemetaan jika Anda menyediakan fungsi pemetaan. (Pada dasarnya, Array.from(str, mappingFunction)adalah [...str].map(mappingFunction)tetapi tanpa array menengah.) Mungkin tidak semua yang relevan di sini diberikan konten string Anda, tetapi dapat menjadi masalah jika string Anda mungkin berisi pasangan pengganti.

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

Jika Anda tidak dapat membuat asumsi itu, tambahkan .filteruntuk memfilter yang tidak cocok:

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

Atau jika Anda ingin menghindari membuat array tambahan yang filterakan dibuat, tetap dengan for-of(atau bahkan Anda 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
sumber
2

Anda dapat menggunakan pemetaan pencarian untuk menyederhanakan 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;
}
Runcing
sumber
Itu menarik, saya tidak berpikir untuk melakukannya dengan cara ini, terima kasih!
CocoFlade
2

Mungkin tidak disingkat tapi jelas lebih bisa dipertahankan.

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

Anda juga bisa:

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

Anda dapat mencoba menggunakan switch casedan fungsi forEach, seperti ini:

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

Anda dapat menggunakan huruf kecil string yang memungkinkan Anda untuk menghapus pemeriksaan string modal:

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