2009-03-11 11 views
0

aşağıdaki sıralı veri var:Algoritma Sıralama Dizeler (Homebrew "uniq -c") Sayma için

AAA 2 
TCG 1 
TTT 3 

Biliyorum: Her dize tekrarlarını saymak istediğiniz

AAA 
AAA 
TCG 
TTT 
TTT 
TTT 

uniq -c kullanarak bunu yapabilir, ancak burada sahip olduğum genel C++ kodunda fazladan işlem yapmam gerekiyor.

I ('pgras' önerisine göre değiştirilmiş) bu yapı ile şaşırıp:

#include <iostream> 
#include <vector> 
#include <fstream> 
#include <sstream> 
using namespace std; 


int main (int arg_count, char *arg_vec[]) { 
    if (arg_count !=2) { 
     cerr << "expected one argument" << endl; 
     return EXIT_FAILURE; 
    } 

    string line; 
    ifstream myfile (arg_vec[1]); 


    if (myfile.is_open()) 
    { 
     int count; 
     string lastTag = ""; 

     while (getline(myfile,line)) 
     { 
      stringstream ss(line); 
      string Tag; 

      ss >> Tag; // read first column 
      //cout << Tag << endl; 

      if (Tag != lastTag) { 
       lastTag = Tag; 
       count = 0; 
      } 
      else { 
       count++; 
      } 

      cout << lastTag << " " << count << endl; 
     } 
     cout << lastTag << " " << count << endl; 
     myfile.close(); 

    } 
    else {cout << "Unable to open file";} 
    return 0; 
} 

Bu yanlış sonuç yazdırır:

AAA 0 
AAA 1 
TCT 0 
TTT 0 
TTT 1 
TTT 2 
TTT 2 
+0

Bu derleme olmayacaktır. Örneğin, sayı tanımlanmamıştır. Senin "ekstra işlemenin" ne olduğu konusunda da net değilim. Daha spesifik olabilir misin? –

+0

@John: Söz konusu uniq etiketini bir değer vererek işleyeceğim ve bu etiketleri sayımla birlikte tekrar yazdıracağız. AAA 2 -40 40 40 – neversaint

+0

Üzgünüm, hala açık değilim. Son örneğinizde "40 40 40" nedir? –

cevap

6

Bunu şey aynıysa etiketi lastTag farklıdır ve artım ne zaman ... sayacını sıfırlamak zorunda ...

+0

@pgras: Ben değiştirdim, ama belki hala seni alamıyorum. – neversaint

+0

Merhaba, Svante cevabı, tam olarak ne demek istediğimi anladım ... – pgras

1

Kodunuz hafifçe sözdizimsel kırık görünüyor (ifstream, ...), ama bence genel algoritma ses. Satırları okuyun ve çizgi her zaman öncekiyle aynı olan bir sayı artırın. Göz önünde bulundurulması gereken bazı sınır koşulları olabilir (eğer girdi sadece bir satırsa?), Ancak test sırasında bunları yakalayacaksınız.

+0

Ve ilk öğe için -1 ile başlamayı unutmayın, aksi halde soru biraz hatalıdır. ;) Yani, şu ana kadar diğer cevaplar verimli değil. – Arafangion

1

Dizginin sadece etiketi almak için kullanılması biraz fazla gibi görünüyor - büyük olasılıkla string :: substr. Bu bir yana, senin kodunda neyin yanlış olduğunu düşünüyorsun? Ne geliştirmek istiyorsun?

Düzenleme: sonraki şey, sizin algoritma ok,

+0

+1, bunun neden düşük olduğunu bilmiyordum ... –

6

sadece dışarı yazdırmak isterseniz ... nefes downvoted elde edilecektir. Başka bir işleve geçmek istiyorsanız, örneğin STL haritasını kullanabilirsiniz. Etiket (count sıfırlamak önce) bu sayım değerini ilişkili olan önceki etiketini işleyebileceği farklı olduğunda

map<string, int> dict; 

while(getline(myfile,line)) { 
      string Tag; 
      stringstream ss(line); 
      ss >> Tag; 
      if (dict.count(Tag) == 0) 
       dict[Tag] = 1; 
      else 
       dict[Tag]++; 
}  
+0

Döngünün içinde fazladan 'if' öğesine ihtiyacınız yok. Varsa, [] işleci varsayılan yapılandırılmış bir öğe oluşturur. –

4
böyle

Kullanım şey:

#include <iostream> 
#include <fstream> 
#include <string> 
#include <algorithm> 
#include <map> 
#include <iterator> 


std::ostream& operator << (std::ostream& out, const std::pair< std::string, size_t >& rhs) 
{ 
    out << rhs.first << ", " << rhs.second; 
    return out; 
} 

int main() 
{ 
    std::ifstream inp("mysorted_data.txt"); 
    std::string str; 
    std::map < std::string, size_t > words_count; 
    while (inp >> str) 
    { 
     words_count[str]++; 
    } 

    std::copy( 
     words_count.begin(), 
     words_count.end(), 
     std::ostream_iterator< std::pair< std::string, size_t > >(std::cout, "\n")); 

    return 0; 
} 
4

veri aslında N olan uzunluğu 3 (veya daha genel uzunluğu N DNA dizeleri oluştuğunu varsayarsak

// Disregard error codes. 
int char2dna_lookup[] = { 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x0 – 0xF 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10 – 0x1F 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x20 – 0x2F 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x30 – 0x3F 
    0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A – P 
    0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Q – 0x5F 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60 – 0x6F 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x70 – 0x7F 
} 

unsigned int hash(string const& dna) { 
    unsigned int ret = 0; 

    for (unsigned int i = 0; i < dna.length(); ++i) 
     ret = ret * 4 + char2dna_lookup[dna[i]]; 

    return ret; 
} 

Artık:) oldukça küçük, sen 4 N bir tablo boyutu ile özel bir karma tablo ve aşağıdaki karma işlevi olan bir q-gram tablosunu kullanarak bu çok verimli yapabilir dizininizi çok verimli bir şekilde indeksleyin.

ifstream ifs("data.txt"); 
string line; 

if (not ifs >> line) 
    exit(1); 

unsigned* frequencies = new unsigned int[line.length()]; 

frequencies[hash(line)] = 1; 

while (ifs >> line) 
    ++frequencies[hash(line)]; 

// Print the frequencies … 

delete[] frequencies; 

Seçenek olarak ise, bu tür görevler için bir kütüphane gibi SeqAn kullanımı.

+0

Uyarı, kod test edilmemiştir. Arama tablosunda (veya başka bir yerde) hatalar olabilir. –

+0

hangi tekniğin bu olduğunu gösteren bir makale yayınlayabilir misiniz? –

2

Ben yapmanız gereken tüm bu bu

 if (Tag != lastTag) { 
      lastTag = Tag; 
      count = 0; 
     } 
     else { 
      count++; 
     } 

     cout << lastTag << " " << count << endl; 

yerine olduğunu düşünüyorum:

 if (Tag != lastTag) { 
      if (lastTag != "") { // don't print initial empty tag 
       cout << lastTag << " " << count << endl; 
      } 
      lastTag = Tag; 
      count = 1; // count current 
      } else { 
      count++; 
     } 
1
#include <map> 
#include <string> 
#include <algorithm> 
#include <iterator> 
#include <iostream> 

class Counter 
{ private: std::map<std::string,int>& m_count; 
    public: Counter(std::map<std::string,int>& data) :m_count(data){} 
     void operator()(std::string const& word) 
     { 
      m_count[word]++; 
     }}; 
class Printer 
{ private: std::ostream& m_out; 
    public: Printer(std::ostream& out) :m_out(out) {} 
     void operator()(std::map<std::string,int>::value_type const& data) 
     { 
      m_out << data.first << " = " << data.second << "\n"; 
     }}; 

int main() 
{ 
    std::map<std::string,int>  count; 

    for_each(std::istream_iterator<std::string>(std::cin), 
      std::istream_iterator<std::string>(), 
      Counter(count) 
      ); 

    for_each(count.begin(),count.end(), 
      Printer(std::cout) 
      ); 
} 
İlgili konular