Подтвердить что ты не робот

Простой словарь в С++

Перемещение кода с Python на С++.

BASEPAIRS = { "T": "A", "A": "T", "G": "C", "C": "G" }

Карты мышления могут быть излишними? Что бы вы использовали?

4b9b3361

Ответ 1

Если вы используете оптимизацию и считаете, что вход всегда один из четырех символов, функция ниже может стоить попробовать заменить карту:

char map(const char in)
{ return ((in & 2) ? '\x8a' - in : '\x95' - in); }

Он работает на основе того, что вы имеете дело с двумя симметричными парами. Условные работы, чтобы отличить пару A/T от G/C, один ( "G" и "C" имеют второй по значению младший бит). Оставшаяся арифметика выполняет симметричное отображение. Это основано на том, что a = (a + b) - b истинно для любых a, b.

Ответ 2

Вы можете использовать следующий синтаксис:

std::map<char, char> my_map = {
    { 'A', '1' },
    { 'B', '2' },
    { 'C', '3' }
};

Ответ 3

В то время как использование std::map в порядке или с использованием таблицы размером char размером 256, было бы прекрасно, вы могли бы сэкономить огромное количество космических агоний, просто используя enum. Если у вас есть функции С++ 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 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
};

Использование становится простым:

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

Если это для вас слишком много, вы можете определить некоторые помощники, чтобы получить персональные символы 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 ];
}

Он чист, прост и эффективен.

Теперь, внезапно, у вас нет 256-байтовой таблицы. Вы также не храните символы (по 1 байт каждый), и, таким образом, если вы пишете это в файл, вы можете записать 2 бита на базовую пару вместо 1 байта (8 бит) на базовую пару. Мне пришлось работать с файлами Bioinformatics, которые сохраняли данные по 1 символу. Преимущество в том, что оно было доступно для человека. Кон - то, что должно было быть 250 МБ файлом, в итоге заняло 1 ГБ места. Движение, хранение и использование были кошмаром. Из coursse, 250 МБ щедро, когда учитывает даже ДНК червя. В любом случае ни один человек не будет читать парные пары на 1 ГБ.

Ответ 4

Пока я действительно был обеспокоен производительностью, я бы использовал функцию, которая берет базу и возвращает ее соответствие:

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

Если бы я был обеспокоен производительностью, я бы определил базу как одну четверть байта. 0 будет представлять A, 1 будет представлять G, 2 будет представлять C, а 3 будет представлять T. Тогда я бы упаковал 4 байт в байт и, чтобы получить их пары, я просто возьму дополнение.

Ответ 5

Таблица из массива char:

char map[256] = { 0 };
map['T'] = 'A'; 
map['A'] = 'T';
map['C'] = 'G';
map['G'] = 'C';
/* .... */

Ответ 6

Здесь решение карты:

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

Ответ 7

BASEPAIRS = { "T": "A", "A": "T", "G": "C", "C": "G" } Что бы вы использовали?

Может быть:

static const char basepairs[] = "ATAGCG";
// lookup:
if (const char* p = strchr(basepairs, c))
    // use p[1]

; -)

Ответ 8

Это самое быстрое, самое простое и маленькое космическое решение, о котором я могу думать. Хороший оптимизирующий компилятор даже удалит стоимость доступа к массивам пар и имен. Это решение работает одинаково хорошо в C.

#include <iostream>

enum Base_enum { A, C, T, G };
typedef enum Base_enum Base;
static const Base pair[4] = { T, G, A, C };
static const char name[4] = { 'A', 'C', 'T', 'G' };
static const Base base[85] = 
  { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1,  A, -1,  C, -1, -1,
    -1,  G, -1, -1, -1, -1, -1, -1, -1, -1, 
    -1, -1, -1, -1,  T };

const Base
base2 (const char b)
{
  switch (b)
    {
    case 'A': return A;
    case 'C': return C;
    case 'T': return T;
    case 'G': return G;
    default: abort ();
    }
}

int
main (int argc, char *args) 
{
  for (Base b = A; b <= G; b++)
    {
      std::cout << name[b] << ":" 
                << name[pair[b]] << std::endl;
    }
  for (Base b = A; b <= G; b++)
    {
      std::cout << name[base[name[b]]] << ":" 
                << name[pair[base[name[b]]]] << std::endl;
    }
  for (Base b = A; b <= G; b++)
    {
      std::cout << name[base2(name[b])] << ":" 
                << name[pair[base2(name[b])]] << std::endl;
    }
};

base [] - это быстрый ascii char to Base (т.е. int между 0 и 3 включительно), который является немного уродливым. Хороший оптимизирующий компилятор должен иметь возможность обрабатывать base2(), но я не уверен, что он делает.