简体   繁体   English

向量在C ++和push_back()中的使用

[英]Use of Vectors of vectors in C++ & push_back( )

I am new to C++ and might be missing something very basic here but I am trying to create a vector of vectors 我是C ++的新手,可能在这里缺少一些非常基本的东西,但是我正在尝试创建向量的向量

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


using namespace std;

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs)
    {
        vector<vector<string>> result;
        map<string,vector<string>> myMap;

        if(strs.size() == 0)
        {
            return result;
        }

        for(string s : strs)
        {
            string temp = s;
            sort(temp.begin(),temp.end());
            auto it = myMap.find(temp);
            if(it != myMap.end())
            {
                it->second.push_back(s);
            }
            else
            {
                vector<string> newVector;
                newVector.push_back(s);
                myMap.insert(pair<string,vector<string>>(temp,newVector));
                result.push_back(newVector);
            }
        }
        cout<< myMap["abt"].size() <<endl;
        return result;
    }
};


int main(int argc, const char * argv[])
{
    Solution mySolution;
    vector<string> myStrings {"eat", "tea", "tan", "ate", "nat", "bat"};
    auto result = mySolution.groupAnagrams(myStrings);

    for(vector<string> v: result)
    {
        //cout << v.size() << endl;
        for(string s: v)
        {
            cout << s << " ";
        }
        cout << endl;
    }
    return 0;
}

I am expecting an output which looks like this 我期望输出看起来像这样

[
  ["ate", "eat","tea"],
  ["nat","tan"],
  ["bat"]
]

When I try to print the vector of vectors in main() I get all the size of the vectors as 1. 当我尝试在main()中打印向量的向量时,向量的所有大小都为1。

Well when I print the sizes of the vectors in the map, the sizes look okay to me there. 好吧,当我在地图上打印矢量的尺寸时,这些尺寸在我看来就可以了。 What am I missing here? 我在这里想念什么?

UPDATE - 更新-

Fixed it with below change 使用以下更改修复了它

for(string s : strs)
{
    string temp = s;
    sort(temp.begin(),temp.end());
    auto it = myMap.find(temp);
    if(it != myMap.end())
    {
        it->second.push_back(s);
    }
    else
    {
        vector<string> newVector;
        newVector.push_back(s);
        myMap.insert(pair<string,vector<string>>(temp,newVector));
    }
}
for(auto it: myMap)
{
    result.push_back(it.second);
}

I would still be interested to know if there is a way to avoid looping through the map in the end and achieve something which I initially intended to do? 我仍然想知道是否有一种方法可以避免最终循环遍历地图并实现我最初打算要做的事情?

It's this part: 这是这部分:

{
    vector<string> newVector;
    newVector.push_back(s);
    myMap.insert(pair<string,vector<string>>(temp,newVector));
    result.push_back(newVector);
}

Each time result is being given a new vector that has one element. 每次给result一个具有一个元素的新向量。 The reason the changes to the map's vector work and not the vector of vectors, is because vector::push_back creates a copy each time. 更改地图矢量工作而非矢量的原因是因为vector::push_back每次都会创建一个副本。


To solve this there's two ways. 为了解决这个问题,有两种方法。

  1. You can try to update the result at the same time as the map, and get the vector to store some reference to the map's copy. 您可以尝试与地图同时更新结果,并获取向量以存储对地图副本的一些引用。
  2. Since you do not use result for the processing step, only for results, you can compile the vector after you're finished with the map. 由于您不将result用于处理步骤,仅将结果用于结果,因此您可以在完成地图后编译向量。

I prefer method #2 for this since you never return the map itself. 我更喜欢方法2,因为您永远不会返回地图本身。 Furthermore there is an art to transforming from one container type to the next, eg this question gives some ideas on what's involved. 此外,还有一种从一种容器类型转换为另一种容器类型的技术,例如, 此问题给出了有关所涉及内容的一些想法。

The problem is with this part of the code: 问题出在这部分代码上:

vector<string> newVector;
newVector.push_back(s);
myMap.insert(pair<string,vector<string>>(temp,newVector));
result.push_back(newVector);

Broken down: 细分:

vector<string> newVector;

Creates a new, local, temporary vector. 创建一个新的本地临时向量。

newVector.push_back(s);

allocates space for a string at the back of newVector and copies s into it. newVector的后面为string分配空间,并将s复制到其中。

myMap.insert(pair<string,vector<string>>(temp,newVector));

Creates a std::pair containing a copy of temp and a copy of newVector - as is, then allocates room for a matching pair in the map and copies the temporary pair (ie copies the string and the vector, again) into it. 按原样创建一个包含temp副本和newVector副本的std :: pair,然后在映射中为匹配对分配空间,然后将临时对复制(即再次复制字符串和向量)到其中。

result.push_back(newVector);

This allocates space for a new vector at the back of result and copies newVector into it. 这将在结果的后面为新向量分配空间,并将newVector复制到其中。

result and myMap contain independent snapshots of newVector at this point. resultmyMap包含的独立快照newVector在这一点上。 The rest of your code updates the vector in myMap but result is untouched. 您的其余代码将更新myMap的向量,但结果保持不变。

You can fix this by not building result on the fly, but only building it when all the work is done: 您可以通过不动态生成result ,而仅在完成所有工作后构建它来解决此问题:

    // take a reference to each string in the vector,
    // const indicates it will be immutable
    for(const string& s : strs)
    {
        string temp = s;
        sort(temp.begin(),temp.end());
        std::vector<string>& dest = myMap[temp];
        dest.emplace_back(s);
    }

    cout<< myMap["abt"].size() <<endl;

    for (auto& kv : myMap)  // kv: key value
    {
        // std::move tells 'emplace_back' it can steal the
        // vector's data right out of kv.second.
        result.emplace_back(std::move(kv.second));
    }

The resulting code is demonstrated here: http://ideone.com/eofloM 结果代码在此处演示: http : //ideone.com/eofloM

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


using namespace std;

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs)
    {
        vector<vector<string>> result;
        map<string,vector<string>> myMap;

        if(strs.size() == 0)
        {
            return result;
        }

        for(const string& s : strs)
        {
            string temp = s;
            sort(temp.begin(),temp.end());
            std::vector<string>& dest = myMap[temp];
            dest.emplace_back(s);
        }

        cout<< myMap["abt"].size() <<endl;

        for (auto& kv : myMap)  // kv: key value
        {
            result.emplace_back(std::move(kv.second));
        }

        return result;
    }
};


int main(int argc, const char * argv[])
{
    Solution mySolution;
    vector<string> myStrings {"eat", "tea", "tan", "ate", "nat", "bat"};
    auto result = mySolution.groupAnagrams(myStrings);

    for(vector<string> v: result)
    {
        //cout << v.size() << endl;
        for(string s: v)
        {
            cout << s << " ";
        }
        cout << endl;
    }
    return 0;
}       

I would still be interested to know if there is a way to avoid looping through the map in the end and achieve something which I initially intended to do? 我仍然想知道是否有一种方法可以避免最终循环遍历地图并实现我最初打算要做的事情?

class Solution {

private:
        vector<vector<string>*> result;
        map<string,vector<string>> myMap;

public:
    vector<vector<string>*> groupAnagrams(vector<string>& strs)
    {
//        vector<vector<string>*> result;
//        map<string,vector<string>> myMap;

simply make the result and map the members of the class. 只需得出结果并映射类的成员即可。 See the type changed to vector of pointers of vector. 请参阅将类型更改为vector的vector的指针。

        else
        {
            vector<string> newVector;
            newVector.push_back(s);
            auto p = myMap.insert(pair<string,vector<string>>(temp,newVector));

            //p is pair<iterator, bool>
            //where iterator is pointing to the inserted element
            //so p.first->second is the new vector

            result.push_back(&(p.first->second));
        }

notice here we put address of the vector in the map. 请注意,我们在地图上放置了向量的地址。

for(vector<string>* v: result)
{
    for(string s: *v)
    {
        cout << s << " ";
    }
    cout << endl;
}

iterating the vector and considering the pointer type gives the result as: 迭代向量并考虑指针类型,结果为:

eat tea ate 
tan nat 
bat

This takes away the second loop and uses less space but makes the code a bit complicated. 这消除了第二个循环并使用了较少的空间,但使代码有点复杂。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM