このコードブロックを改善および短縮するにはどうすればよいですか?[閉まっている]


9

この関数は、「GTCA」などのDNAの文字列を取り、正しく一致する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;
}

これは正しいです。しかし、私はそれを書くより短くて簡単な方法を見つけようとしています。誰かが私が使うべきものを手伝ってくれる?


1
このメソッドを簡単に使用するdna [i] .toLowerCase()
Thaier Alkhateeb

9
コードが機能し、改善が必要な場合は、codereview.stackexchange.comを
Peter Collingridge

このコードは意図したとおりに| 機能するとは思わず、Javascriptのような論理ORも実行しない||
Ma'moun othman

2
@mamounothman-それは事実ですが、どちらもそのコードで機能します(||ただし、より優れています)。
TJクラウダー

回答:


14

次の手順でコードを改善できます。

  • 複数のifステートメントがあり、すべてが同じ構造である場合、おそらくオブジェクトを使用する必要があります
  • 大文字と小文字の両方をチェックする必要があります。toLowerCase()入力時に使用するだけです。
  • あなたsplitは文字列とmap()配列のpush()値を作成するのではなくそれを使用ます。

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

}

文字列に他の特定の文字を含めることができる場合は、後filter()undefined値を指定する必要がありますmap

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

@RobGがコメントで言及したもう1つの優れた点は、ループする前に文字列から不要な文字を削除できることです。

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

1
dnaにリストされていない文字が含まれている場合undefined、最終的な配列に値が含まれます。
グレゴリーNEUT

1
@GrégoryNEUT私の回答にそのケースの修正を追加しました
Maheer Ali

または、で文字列を前処理できますdna.toLowerCase().replace(/[^cgta]/g,'')...。;-)
RobG

@RobG本当に気に入りました。私はそれを私の答えに追加しました。
Maheer Ali

1
紐だったので見逃しました。:-) FWIW、文字列を配列に分割するよりUnicodeに優しい方法は今です[...dna]。サロゲートペアを分割しません。(またはArray.from、あなたがマップしようとしている場合に特に有用である:Array.from(dna, mappingFunction)。)(ここではすべてのことは関係ありませんが、私は仮定dnaだけ含まれているcgt、とa。)
TJクラウダー

3

私はおそらく:

  1. for-ofループを使用します(または可能なフィルタリングを使用してマッピングします)

  2. ルックアップオブジェクトまたはマップを使用する

  3. 切り替え/検索時に文字列を小文字または大文字にします(ただし、切り替え/検索の重複したエントリも機能します)。

/ 、/ 、/ /、または/ dnaのみが含まれることがわかっている場合(私が理解しているように、これはDNAにも当てはまります;-))、ルックアップオブジェクト/マップでそのマッピング機能を使用できます。cCgGtTaAArray.from

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

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

私が使用しArray.fromているのは、コード単位だけでなく(サロゲートペアを分割しない)コードポイントで文字列を分割し、マッピング関数を提供した場合にマッピング機能があるためです。(基本的にArray.from(str, mappingFunction)はです[...str].map(mappingFunction)が、中間配列はありません。)文字列の内容を考えると、おそらくここで関連するものはすべてではありませんが、文字列にサロゲートペアが含まれている場合は問題になる可能性があります。

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

その仮定を行うことができない場合は、追加.filterして、一致しなかったものを除外します。

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

または、作成する追加の配列の作成を避けたい場合はfilterfor-of(または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

ルックアップマッピングを使用してループを簡略化できます。

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

これは面白いと思いました。このように考えたわけではありません。ありがとうございます。
CocoFlade

2

多分短縮されないかもしれませんが、確実により保守可能です。

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

あなたも行うことができます:

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

次のようにswitch caseforEach関数を使用してみてください:

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

あなたは大文字の文字列のチェックを削除することを可能にする文字列を小文字にすることができます:

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;

}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.