C++ C+中的二维迭代器访问+;

C++ C+中的二维迭代器访问+;,c++,iterator,stdmap,C++,Iterator,Stdmap,我正在使用std::map()处理一个二维表,以计算一个数字转换到另一个数字的次数。我遇到了两个问题。首先,我的第一次转换没有显示(1->2)。其次,我所有的转换只显示一次(2->3和3->1都出现两次) 我能理解为什么这种转变只发生一次。迭代器没有看到currentVal,而是转到else,在那里添加值,然后退出。但我不知道如何解决这个问题。感谢您的帮助 #include <iostream> #include <map> #include <algorithm&

我正在使用std::map()处理一个二维表,以计算一个数字转换到另一个数字的次数。我遇到了两个问题。首先,我的第一次转换没有显示(1->2)。其次,我所有的转换只显示一次(2->3和3->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>()));
        }
    }
}
#包括
#包括
#包括
#包括
使用名称空间std;
//导入midi音符
向量midiFile={1,2,3,1,20,5,2,3,1};
//为矩阵创建二维哈希映射
地图计数;
//前一个值和当前值的字符串
字符串prevVal=“”;
字符串currentVal=“”;
void addNumbers(矢量MIDI文件){
对于(int i=0;i秒;
mCounts[prevVal][currentVal]=计数器+1;
}否则{
播放计数。插入(对(当前值,1));
mCounts[prevVal]=播放计数;
}
prevVal=当前值;
}
//查找映射中已存在的值
对它进行迭代器;
它=mCounts.find(prevVal);
if(it!=mCounts.end()){
//如果找到值,则不执行任何操作
}否则{
插入(pair(prevVal,map());
}
}
}

尝试以下方法,将构成转换的两个整数组合成一个字符串,格式为
“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;
}

这里的解决方案不使用嵌套映射,也不将注释转换为字符串(但假设注释为非负):

//此代码段使用c++11语法
#包括
//本例中的代码假设有效注释为非负
结构转换{
int from;
int到;
};
//使转换可用为
//输入std::map
布尔运算符<(常数变换和l、常数变换和r){
返回l.from秒;
}否则{
返回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';
}
#包括
#包括
int main(){
向量注释={1,2,3,1,20,5,2,3,1};
标准::映射转换计数器;
int上一个注释=-1;
for(int注释:notes){
如果(上一个注释!=-1){
过渡t{先前的注释,注释};
转换_计数器[t]+=1;
}
以前的注释=注释;
}

std::cout您处理的是<128的小整数。只需使用一个矩阵,其中
transition[i][j]
是从i到j的转换次数。通常我建议为具有索引乘法的矩阵使用一个平面缓冲区来访问2d维度,或者使用一个预先编写的类包装器(请参阅).但是在这种情况下,矩阵太小了,你可以用

int transition[128][128];
当然,您希望键入def并通过引用传递它。 不仅所有的操作都会更简单、更透明,而且使用转移矩阵可以进行任何其他方式都不可能的分析:平衡态的特征向量,等等

对于更大的问题,其中转换是稀疏的,并且您负担不起密集矩阵,请使用实际的稀疏矩阵类,这基本上是您自己尝试滚动的

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]++;
    }
}
typedef int transitionMatrix[128][128];
void addNumbers(常量向量和midiFile、传递矩阵和mCounts){
对于(int i=0;i
请尝试并避免养成使用命名空间std
的习惯。这可能会导致以后的大量混乱。我认为在循环中创建
playCounts
正确吗,即在每次循环迭代中创建一个空映射?顺便说一句:我建议使用单个映射(而不是“2D”映射)使用一个像
2..3
这样的转换作为一个像
2->3
这样的单键,并相应地管理计数。谢谢tadman。是的Stephan,这是一个很好的观点。我创建它时认为每个迭代都有不同的值,但可能我需要将
playCounts
作为一个全局变量。好的,我已经创建了
playCounts
global,这修复了大多数转换,尽管其中一些不正确。请欣赏。我唯一关心的是,我将使用这些转换来定义实时播放的midi音符(马尔可夫链)因此,当音符20播放时,我需要一种方法将该数字引用到其相应的转换(20->5)中,但这些值是链接在一起的。我能看到的唯一方法是添加一个外部贴图,除非你看到另一种方法?这非常有效。这是我的初始步骤
int transition[128][128];
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]++;
    }
}