交换字符串中的字母

我需要用以下规则交换字符串中的字母:

  • A由T代替
  • T由A代替
  • C由G代替
  • G由C代替

例如: ACGTA应该成为TGCAT

解决这个问题的最佳方法是什么?

搜索java "A to T, T to A"找到了这个建议 :

 String sequence = "AATTTCTCGGTTTCAAT"; sequence = sequence.replace("A", "t") .replace("T", "a") .replace("C", "g") .replace("G", "c") .toUpperCase(); System.out.println(sequence); 

这是一个简单而简洁的解决方案,适用于您的特定情况,如果您的DNA字符串相对较短,将具有可接受的性能。 对于处理大量数据的更通用的解决方案,您应该逐个遍历字符并构建新的字符串。 或者作为多基因润滑剂指出 – 考虑一种存储格式,每个基数仅使用2位而不是16位。

我会寻求一个更通用的解决方案:

 public String tr(String original, String trFrom, String trTo) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < original.length(); ++i) { int charIndex = trFrom.indexOf(original.charAt(i)); if (charIndex >= 0) { sb.append(trTo.charAt(charIndex)); } else { sb.append(original.charAt(i)); } } return sb.toString(); } 

调用这样的函数会得到你需要的结果:

 tr("ACGTA", "ATCG", "TAGC") 

所以该函数与unix tr实用程序几乎相同:

 echo ACGTA | tr ATCG TAGC 

就像我昨天解释的那样 ,Strings是不可变的,你不能改变一个String,你必须创建一个新的并替换旧的。

你可以这样解决你的问题:

 String s = "ACGTA"; StringBuilder sb= new StringBuilder(); for (char c:s.toCharArray()) { switch(c) { case 'A': sb.append('T');break; case 'T': sb.append('A');break; case 'C': sb.append('G');break; case 'G': sb.append('C');break; default: //handle error here -> invalid char in String } } s = sb.toString(); 

这个解决方案的优点是你不会创建太多的String对象(每个’replace’操作都会创建一个新的String,如果你必须恢复很多 dna序列,这会破坏性能)


这是基于polygenelubricants和rsp的非常有用的评论的更高性能版本:

 String s = "ACGTA"; char[] reverse = new char[s.length()]; for (int i = 0; i < reverse.length; i++) { switch(s.charAt(i)) { case 'A': reverse[i] = 'T';break; case 'T': reverse[i] = 'A';break; case 'C': reverse[i] = 'G';break; case 'G': reverse[i] = 'C';break; default: //handle error here -> invalid char in String } } s = new String(reverse); 

DNA有一个小字母表。 您可以使用查找表 ,使用简单的数组索引替换某些语句。

这种方法:

  • 仅遍历序列一次。
  • 消除条件语句。
  • 在字母案例方面可以是稳定的,有时用于传递DNA序列中的信息。
  • 可以处理IUPAC模糊代码。
  • 可以处理差距。
  • 可以轻松提供反向补充

首先,您需要一个查找表。

 private static final String COMPLEMENT_TABLE // 0123456789ABCDEF0123456789ABCDEF = " " // 0-31 + " - " // 32-63 + " TVGH CD M KN YSAABWXR " // 64-95 + " tvgh cd m kn ysaabwxr "; // 96-127 // ABCDEFGHIJKLMNOPQRSTUVWXYZ private static final byte[] COMPLEMENT_TABLE_BYTES = COMPLEMENT_TABLE.getBytes( StandardCharsets.US_ASCII ); 

然后,您可以通过简单的表查找找到补语的基础。

 public static byte[] complement( byte[] sequence ) { int length = sequence.length; byte[] result = new byte[ length ]; for ( int i = 0; i < length; ++i ) { result[i] = COMPLEMENT_TABLE_BYTES[ sequence[i] ]; } return result; } 

如果为了方便使用小序列,您可以提供接受并返回String的方法。

 public static String complement( String sequence ) { byte[] complementBytes = complement( sequence.getBytes( StandardCharsets.US_ASCII )); return new String( complementBytes, StandardCharsets.US_ASCII ); } 

可以在同一循环中计算反向补码。

 public static byte[] reverseComplement( byte[] sequence ) { int length = sequence.length; byte[] result = new byte[ length ]; for ( int i = 0; i < length; ++i ) { result[ (length - i) - 1] = COMPLEMENT_TABLE_BYTES[ sequence[i] ]; } return result; } public static String reverseComplement( String sequence ) { byte[] complementBytes = reverseComplement( sequence.getBytes( StandardCharsets.US_ASCII )); return new String( complementBytes, StandardCharsets.US_ASCII ); } 

使用您的示例序列:

 public static void main(String[] args) { String sequence = "ACGTA"; String complementSequence = complement( sequence ); System.out.println( String.format( "complement(%s) = %s", sequence, complementSequence )); String reverseComplementSequence = reverseComplement( sequence ); System.out.println( String.format( "reverseComplement(%s) = %s", sequence, reverseComplementSequence )); } 

我们得到这个输出:

 complement(ACGTA) = TGCAT reverseComplement(ACGTA) = TACGT