C++中的简单字典

y2k*_*y2k 38 c++ dictionary map

将一些代码从Python转移到C++.

BASEPAIRS = { "T": "A", "A": "T", "G": "C", "C": "G" }
Run Code Online (Sandbox Code Playgroud)

思维导图可能有点矫枉过正?你会用什么?

Sta*_*ked 61

您可以使用以下语法:

#include <map>

std::map<char, char> my_map = {
    { 'A', '1' },
    { 'B', '2' },
    { 'C', '3' }
};
Run Code Online (Sandbox Code Playgroud)

  • 仅在C++ 11中. (20认同)

jog*_*pan 19

如果您正在进行优化,并假设输入始终是四个字符之一,则下面的函数可能值得尝试替换地图:

char map(const char in)
{ return ((in & 2) ? '\x8a' - in : '\x95' - in); }
Run Code Online (Sandbox Code Playgroud)

它的工作原理是您正在处理两个对称对.条件用于将A/T对与G/C对分开('G'和'C'碰巧具有共同的第二最低有效位).剩下的算术执行对称映射.它基于a =(a + b) - b对于任何a,b都是正确的事实.


小智 16

虽然使用a std::map很好或使用256大小的char表就可以了,但只需使用一个就可以节省大量的空间痛苦enum.如果您具有C++ 11功能,则可以使用enum class强类型:

// First, we define base-pairs. Because regular enums
// Pollute the global namespace, I'm using "enum class". 
enum class BasePair {
    A,
    T,
    C,
    G
};

// Let's cut out the nonsense and make this easy:
// A is 0, T is 1, C is 2, G is 3.
// These are indices into our table
// Now, everything can be so much easier
BasePair Complimentary[4] = {
    T, // Compliment of A
    A, // Compliment of T
    G, // Compliment of C
    C, // Compliment of G
};
Run Code Online (Sandbox Code Playgroud)

用法变得简单:

int main (int argc, char* argv[] ) {
    BasePair bp = BasePair::A;
    BasePair complimentbp = Complimentary[(int)bp];
}
Run Code Online (Sandbox Code Playgroud)

如果这对你来说太过分了,你可以定义一些助手来获得人类可读的ASCII字符,并且还可以得到基础对的赞美,这样你就不会一直在进行(int)强制转换:

BasePair Compliment ( BasePair bp ) {
    return Complimentary[(int)bp]; // Move the pain here
}

// Define a conversion table somewhere in your program
char BasePairToChar[4] = { 'A', 'T', 'C', 'G' };
char ToCharacter ( BasePair bp ) {
    return BasePairToChar[ (int)bp ];
}
Run Code Online (Sandbox Code Playgroud)

它干净,简单,高效.

现在,突然间,你没有256字节的表.您也没有存储字符(每个字节1个字节),因此如果您将其写入文件,则每个碱基对可以写入2位而不是每个碱基对1个字节(8位).我不得不使用生物信息学文件,每个文件存储数据为1个字符.好处是它是人类可读的.该骗局应该是一个250 MB的文件最终占用1 GB的空间.运动,储存和使用是一场噩梦.对于coursse来说,即使是蠕虫DNA ,250 MB也是慷慨的.无论如何,没有人会阅读1 GB的碱基对.

  • 它......根本就没有这样做.我正在索引一个数组.这都是O(1). (3认同)

Ben*_*ley 10

在我真正关注性能之前,我会使用一个函数,它接受一个基数并返回它的匹配:

char base_pair(char base)
{
    switch(base) {
        case 'T': return 'A';
        ... etc
        default: // handle error
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我关心性能,我会将一个基数定义为一个字节的四分之一.0代表A,1代表G,2代表C,3代表T.然后我将4个字节打包成一个字节,为了得到它们的对,我只需要补码.


per*_*eal 8

char数组中的表:

char map[256] = { 0 };
map['T'] = 'A'; 
map['A'] = 'T';
map['C'] = 'G';
map['G'] = 'C';
/* .... */
Run Code Online (Sandbox Code Playgroud)

  • @spin_eight,这是一个直接访问表,查找是O(1) (4认同)
  • 那是一张很奇怪的地图。 (2认同)
  • 这是一张极其浪费的地图。但是,它……完成了工作……? (2认同)
  • @ThePhD,令人难以置信?使用256个字节.std :: map的开销是多少?什么是查找时间? (2认同)
  • 您是否意识到这可以通过简单的枚举和函数来实现?如果你想获得更多的幻想,可以将该枚举用于其他枚举的表中,并且只使用4个字节.如果你真的想研磨一些光学装置,你可以将ATCG打包成2位(就像DNA的最明显的二进制表示一样).`char`不是DNA结构的数据类型(有一个原因,DNA列表文件的ASCII大4倍). (2认同)

con*_*gus 5

这是地图解决方案:

#include <iostream>
#include <map>

typedef std::map<char, char> BasePairMap;

int main()
{
    BasePairMap m;
    m['A'] = 'T';
    m['T'] = 'A';
    m['C'] = 'G';
    m['G'] = 'C';

    std::cout << "A:" << m['A'] << std::endl;
    std::cout << "T:" << m['T'] << std::endl;
    std::cout << "C:" << m['C'] << std::endl;
    std::cout << "G:" << m['G'] << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 不相关,但你正在过度冲洗流. (6认同)
  • @Rapptz:我想知道你所说的“过度刷新”是什么意思,直到我发现“std::endl”同时执行“\n”(换行符)和“std::flush”。 (3认同)