2017-03-28 13 views
0

std :: map()を使用して2Dテーブルを作成して、1つの数値が別の数値に何回遷移するかを計算しています。私は2つの問題に遭遇しました。まず、私の最初の移行は表示されません(1 - > 2)。第二に、私のすべてのトランジションは1回しか表示されません(2-> 3および3-> 1両方が2回起こります)。C++での2Dイテレータアクセス

遷移が1回だけ起こっているのがわかります。イテレーターはcurrentValを表示せず、elseに行きます。ここで値を加算して終了します。私はこれを修正する方法はわかりません。どんな助けもありがとう!

#include <iostream> 
#include <map> 
#include <algorithm> 
#include <vector> 

using namespace std; 

//import midi notes 
vector <int> midiFile = {1, 2, 3, 1, 20, 5, 2, 3, 1}; 

//create a 2d hashmap for matrix 
map <string, map <string, int> > mCounts; 

//strings for the previous value and current value 
string prevVal = ""; 
string currentVal = ""; 

void addNumbers(vector <int> midiFile) { 

    for (int i = 0; i < midiFile.size(); i++) { 
     currentVal = to_string(midiFile[i]); 

     if(prevVal == "") { 
      prevVal = currentVal; //first value 
     } else { 
      //playCounts is temporary map to store counts of current val in relation to previous val 
      map <string, int> playCounts; 

      map <string, int> ::iterator iterator; 
      iterator = playCounts.find(currentVal); 

      //if mCounts doesn't contain the value yet, create a new hashmap 
      if(iterator != playCounts.end()){ 

       int counter = iterator -> second; 
       mCounts[prevVal] [currentVal] = counter + 1; 


      } else { 
       playCounts.insert(pair <string, int>(currentVal, 1)); 
       mCounts [prevVal] = playCounts; 

      } 

      prevVal = currentVal; 

     } 

     //find values already in map 
     map <string, map <string, int> > ::iterator it; 
     it = mCounts.find(prevVal); 

     if (it != mCounts.end()) { 
      //if value is found, do nothing 
     } else { 
      mCounts.insert(pair <string, map <string, int>>(prevVal, map <string, int>())); 
     } 
    } 
} 
+0

「名前空間の使用」の習慣を試してみてください。後で多くの混乱を招く可能性があります。 – tadman

+0

ループ内で 'playCounts'を作成するのが正しいかどうか、つまり各ループ反復で空のマップを作成するのは正しいですか? –

+0

ところで:「2D」マップではなく)1つのマップを使用し、 '2 .. 3'のようなトランジションを' 2-> 3 'のような単一のキーとして使用し、それに応じて数を管理することをお勧めします。 –

答えて

0

あなたは小さな整数を扱っています< 128です。ちょうどtransition[i][j]がiからjへの遷移数である行列を使用してください。通常は、2次元にアクセスするためのインデックス乗算、または同じものの周りにあらかじめ書き込まれたクラスラッパー(Eigen参照)を持つ行列用のフラットバッファをお勧めします。しかし、この場合には、マトリックスが非常に小さいので、あなただけもちろん

​​

を使用することができますが、これをtypedefを参照することによって、それを通過したいです。 あなたのすべての操作がより簡単で透明になるだけでなく、平衡状態などのための固有ベクトルなど、密な行列を用意するには、本質的に自分自身を動かそうとしている実際の疎な行列クラスを使用します。

typedef int transitionMatrix[128][128]; 

void addNumbers(const vector <int> &midiFile, transitionMatrix &mCounts) { 
    for (int i = 0; i < midiFile.size()-1; i++) { 
     int prev = midiFile[i]; 
     int curr = midiFile[i+1]; 
     mCounts[prev][curr]++; 
    } 
} 
+0

これは本当にうまく動作します。これは最初のアプローチ方法ですが、128x128の行列が計算に多くなると考えました。もう1つの質問。 'mCounts'の結果は、forループを通して' midiFile'プロセスとして出力されますが、forループが終了するとすべての結果を出力するだけです。これに関するアイデア?私のランダム化の重みを計算するにつれて、カウントが結果を歪めるかもしれないと心配しています。ありがとう。 –

+0

印刷コードは表示されていません。上記のスニペットでは何も印刷されません。 'addNumbers'を呼び出した後は、完成した行列が得られますが、必要に応じて印刷することができます。おそらく、両方のインデックスに対して二重ループを実行し、ゼロ以外をテストし、インデックスとカウントを出力するprintメソッドが必要になります。 – Peter

0

遷移を構成する2つの整数は、次にカウントマップのキーとして機能する形態"1->2"、単一の文字列に結合された以下の手法を試してみてください。コードはそのように簡潔になります。さらに、私はグローバル変数を排除し、それらのローカルなものやパラメータ製:

#include <iostream> 
#include <map> 
#include <vector> 
#include <sstream> 

using std::vector; 
using std::map; 
using std::string; 

void addNumbers(const vector <int> &midiFile, map <string, int> &mCounts) { 

    for (int i = 0; i < midiFile.size()-1; i++) { 

     int prev = midiFile[i]; 
     int curr = midiFile[i+1]; 
     std::stringstream ss; 
     ss << prev << "->" << curr; 

     mCounts[ss.str()]++; 
    } 
} 


int main(int argc, char* argv[]) 
{ 
    vector <int> midiFile = {1, 2, 3, 1, 20, 5, 2, 3, 1}; 
    map <string, int> mCounts; 

    addNumbers(midiFile, mCounts); 
    for (auto const& x : mCounts) 
    { 
     std::cout << x.first // transition 
     << ':' 
     << x.second // count 
     << std::endl ; 
    } 

    return 0; 
} 

出力:ここ

1->2:1 
1->20:1 
2->3:2 
20->5:1 
3->1:2 
5->2:1 
+0

これを感謝します。このアプローチの私の唯一の懸念は、これらのトランジションを使って、リアルタイムで演奏される予定のMIDIノート(マルコフチェーン)を定義することです。ノート20が演奏されるとき、その番号を適切なトランジション(20→5)に参照する方法が必要ですが、値はリンクされています。私がこれを行うために見ることができる唯一の方法は、別の方法を見ない限り、外側の地図を追加することです。 –

0

は、ネストされたマップを使用しないソリューションであり、(文字列にメモを変換しませんが、 )ノートは非負であることを前提としています

// This snippet uses c++11 syntax 
#include <map> 

// Code in this example assumes that valid notes are nonnegative 
struct transition { 
    int from; 
    int to; 
}; 

// Comparison operator required to make transition usable as a 
// key in std::map 
bool operator< (const transition& l, const transition& r) { 
    return l.from < r.from || (l.from == r.from && l.to < r.to); 
} 

// Range of all transitions with respective counter 
// starting from a particular note 
std::pair<std::map<transition, int>::const_iterator, 
    std::map<transition, int>::const_iterator> 
transitions_from(int from_note, 
     const std::map<transition, int>& transition_counters) { 
    return std::make_pair(transition_counters.lower_bound(transition{from_note, -1}), 
      transition_counters.upper_bound(transition{from_note + 1, -1})); 
} 

int counter_for(transition t, const std::map<transition, int>& transition_counters) { 
    const auto it = transition_counters.find(t); 
    if (it != transition_counters.end()) { 
     return it->second; 
    } else { 
     return 0; 
    } 
} 

使用例:

#include <iostream> 
#include <vector> 

int main() { 
    std::vector<int> notes = {1, 2, 3, 1, 20, 5, 2, 3, 1}; 
    std::map<transition, int> transition_counters; 
    int previous_note = -1; 
    for (int note: notes) { 
     if (previous_note != -1) { 
      transition t{previous_note, note}; 
      transition_counters[t] += 1; 
     } 
     previous_note = note; 
    } 

    std::cout << "all encountered transitions:\n"; 
    for (const auto& entry: transition_counters) { 
     std::cout << '(' << entry.first.from << " -> " << entry.first.to << "): " << entry.second << '\n'; 
    } 

    std::cout << "transitions from 1:\n"; 
    const auto transitions_from_1 = transitions_from(1, transition_counters); 
    for (auto it = transitions_from_1.first; it != transitions_from_1.second; ++it) { 
     std::cout << '(' << it->first.from << " -> " << it->first.to << "): " << it->second << '\n'; 
    } 

    std::cout << "counters for individual transitions:\n"; 
    std::cout << "(1 -> 2): " << counter_for(transition{1, 2}, transition_counters) << '\n'; 
    std::cout << "(2 -> 1): " << counter_for(transition{2, 1}, transition_counters) << '\n'; 
}