背景:我是 C++ 领域的 rockie
输入文件: 100万行
FCC5G2YACXX:5:1101:1224:2059#NNNNNNNN 97 基因组 96003934 24 118M4D11M = 96004135 0 GCA....ACG P\..GW^EO AS:i:-28 XN:i:0 XM:i:2 XO: i:1 XG:i:4 NM:i:6 MD:Z:54G53T9^TACA11 YT:Z:UP
预期产出
96003934 98.31
解释输出
第 4 栏:96003934
第 18 栏:MD:Z:54G53T9^TACA11
匹配 = 54+53+9 = 116
不匹配 = count_letter(54G53T9) = 2
id = 116*100 / (116+2) = 98.30508474576272
awk 脚本
awk '{
split($18,v,/[\^:]/);
nmatch = split(v[3],vmatch, /[^0-9]/);
cmatch=0;
for(i=1; i<=nmatch; i++) cmatch+=vmatch[i];
printf("%s"OFS"%.2f\n", $4, cmatch*100/(cmatch+nmatch-1));
}' file.sam
Run Code Online (Sandbox Code Playgroud)
C++,我认为会更快
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <iomanip>
using namespace std;
int main(){
string line;
while(getline(cin, line)){
istringstream iss(line);
vector<string> columns;
copy(istream_iterator<string>(iss), //Split line by spaces
istream_iterator<string>(),
back_inserter(columns));
//I extract information from column 18
int start = columns[17].find_last_of(':');
int end = columns[17].find_first_of('^');
string smatch = columns[17].substr(start+1, end-start-1);
// I get for example "54G53T9"
replace( smatch.begin(), smatch.end(), 'A', ' ');
replace( smatch.begin(), smatch.end(), 'C', ' ');
replace( smatch.begin(), smatch.end(), 'G', ' ');
replace( smatch.begin(), smatch.end(), 'T', ' ');
// I get for example "54 53 9"
istringstream iss_sum(smatch);
int n=0, sum=0, count=0;
while(iss_sum >> n){
sum += n;
count++;
}
cout << columns[3] << ' ' << fixed << setprecision(2)
<< (float)sum*100 / (sum+count-1) << endl;
}
}
Run Code Online (Sandbox Code Playgroud)
基准
输入有 100 万行......
问题
我做错了什么,所以C++工作缓慢?.....我可以改进C++程序吗?如果是,怎么办?.....我应该写进去C吗?....
预先感谢
C++ iostreams 并没有真正提供一种好的方法来检查某些输入中是否存在列,但会忽略它。C++ iostreams 有一个ignore,但它不太适合这种特殊情况,所以它可能没有帮助。
既然如此,我至少会考虑使用scanf,可能是这个一般顺序上的东西:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <string>
#include <iostream>
#include <numeric>
int main() {
char column4[256];
char column17[256];
while (2 == scanf("%*s %*s %*s %255s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %255s %*s", column4, column17)) {
char *beg = strrchr(column17, ':') + 1;
char *end = strchr(column17, '^');
*end = '\0';
int nums[5];
int count = sscanf(beg, "%d%*[A-Z]%d%*[A-Z]%d%*[A-Z]%d%*[A-Z]%d", nums, nums + 1, nums + 2, nums + 3, nums + 4);
int sum = std::accumulate(nums, nums + count, 0);
double result = (sum*100.0) / (sum + count-1);
printf("%s %2.2f\n", column4, result);
}
}
Run Code Online (Sandbox Code Playgroud)
目前,这假设(也许是错误的,但我必须猜测一些)第 17 列(或者,我将其算作第 18 列,但无论如何)从开始到最后一个冒号 ( ) 都可以被忽略:。然后是任意数量的数字重复,然后是字母,另一个数字,另一个字母等等(暂时假设以数字开头和结尾)。目前,我最多允许使用 5 个数字,但允许更多数字就没什么意义了。允许模式中有更多变化可能需要更多的工作(取决于可能发生哪种变化。
为了提高速度,您可以使用更大的输入缓冲区,如下所示:
setvbuf(stdin, NULL, _IOFBF, 65536);
Run Code Online (Sandbox Code Playgroud)
您需要/想要在阅读任何内容之前执行此操作,因此它会在while循环之前执行。确切地说,这会带来多大的好处(如果有的话)似乎有所不同,但它很容易做到,至少值得尝试一下,看看它是否有任何不同。
| 归档时间: |
|
| 查看次数: |
1930 次 |
| 最近记录: |