【问题标题】:How can I improve and shorten this block of code? [closed]如何改进和缩短这段代码? [关闭]
【发布时间】:2020-05-26 21:41:26
【问题描述】:

此函数接受一串 DNA,例如“GTCA”,并返回一个包含正确匹配的 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;
}

这是正确的。但是,我正在尝试找到一种更短,更简单的编写方式。任何人都可以帮我解决我应该使用的东西吗?

【问题讨论】:

  • 轻松使用这个方法 dna[i].toLowerCase()
  • 如果您的代码有效并且您只想改进,请尝试codereview.stackexchange.com
  • 我不认为这段代码能按预期工作,| 不像 || 那样在 Javascript 中执行逻辑 OR
  • @mamounothman - 没错,但两者都可以在该代码中工作(不过|| 会更好)。

标签: javascript arrays for-loop


【解决方案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;
}

【讨论】:

    【解决方案2】:

    您可以通过以下步骤改进您的代码:

    • 当有多个 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()])
    
    }

    如果字符串可以包含除特定字母以外的任何内容,那么您需要在map 之后将undefined 值添加到filter()

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

    @RobG 在 cmets 中提到了另一个更好的方法,我们可以在遍历字符串之前从字符串中删除不需要的字母。

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

    【讨论】:

    • 如果 dna 包含未列出的字符,您的最终数组中将有 undefined 值。
    • @GrégoryNEUT 在我的回答中添加了针对这种情况的修复
    • 或者您可以使用dna.toLowerCase().replace(/[^cgta]/g,'')... 预处理字符串。 ;-)
    • @RobG 真的很喜欢。我把它添加到我的答案中。
    • 我错过了它是一个字符串。 :-) FWIW,现在是[...dna],一种更加 Unicode 友好的将字符串拆分为数组的方式。它不会破坏代理对。 (或Array.from,如果您要映射:Array.from(dna, mappingFunction),这将特别有用。)(此处并非所有相关,我假设dna 仅包含cgta.)
    【解决方案3】:

    您可以使用查找映射来简化循环:

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

    【讨论】:

    • 这很有趣,我没想到会这样做,谢谢!
    【解决方案4】:

    也许不会缩短,但肯定更易于维护。

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

    【讨论】:

      【解决方案5】:

      您可以尝试使用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;
      }
      

      【讨论】:

        【解决方案6】:

        我可能会:

        1. 使用for-of 循环(或可能带有过滤的映射)

        2. 使用查找对象或地图

        3. 在切换/查找时使字符串小写或大写(但在切换/查找中重复的条目也可以):

        如果您知道 dna 将只包含 c/Cg/Gt/T/ 或 a/A(其中,据我了解,DNA 是这样的 ;-) ),那么您可以使用 Array.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);
        }
        

        或者,如果您想避免创建 filter 会创建的额外数组,请坚持使用 for-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;
        }
        

        【讨论】:

          【解决方案7】:
          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;
          
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-08-04
            • 1970-01-01
            • 2013-11-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多