Construction a vector from the concatenation of 2 vectors

后端 未结 6 433
梦谈多话
梦谈多话 2021-01-12 22:45

Is there a way to construct a vector as the concatenation of 2 vectors (Other than creating a helper function?)

For example:



        
相关标签:
6条回答
  • 2021-01-12 23:20

    I came across this question looking for the same thing, and hoping there was an easier way than the one I came up with... seems like there isn't.

    So, some iterator trickery should do it if you don't mind a helper template class:

    #include <vector>
    #include <iostream>
    
    template<class T>
    class concat
    {
    public:
        using value_type = typename std::vector<T>::const_iterator::value_type;
        using difference_type = typename std::vector<T>::const_iterator::difference_type;
        using reference = typename std::vector<T>::const_iterator::reference;
        using pointer = typename std::vector<T>::const_iterator::pointer;
        using iterator_category = std::forward_iterator_tag;
        concat(
            const std::vector<T>& first,
            const std::vector<T>& last,
            const typename std::vector<T>::const_iterator& iterator) : 
                mFirst{first},
                mLast{last},
                mIterator{iterator}{}
        bool operator!= ( const concat& i ) const
        {
            return mIterator != i.mIterator;
        }
        concat& operator++()
        {
            ++mIterator;
            if(mIterator==mFirst.end())
            {
                mIterator = mLast.begin();
            }
            return *this;
        }
        reference operator*() const
        {
            return *mIterator;
        }
    private:
        const std::vector<T>& mFirst;
        const std::vector<T>& mLast;
        typename std::vector<T>::const_iterator mIterator;
    };
    
    int main()
    {
        const std::vector<int> first{0,1,2,3,4};
        const std::vector<int> last{5,6,7,8,9};
        const std::vector<int> concatenated(
            concat<int>(first,last,first.begin()),
            concat<int>(first,last,last.end()));
        for(auto i: concatenated)
        {
            std::cout << i << std::endl;
        }
        return 0;
    }
    

    You may have to implement operator++(int) or operator== depending on how your STL implements the InputIterator constructor, this is the minimal iterator code example I could come up with for MingW GCC.

    Have Fun! :)

    0 讨论(0)
  • 2021-01-12 23:23

    I think you have to write a help function. I'd write it as:

    std::vector<int> concatenate(const std::vector<int>& lhs, const std::vector<int>& rhs)
    {
        auto result = lhs;
        std::copy( rhs.begin(), rhs.end(), std::back_inserter(result) );
        return result;
    }
    

    The call it as:

        const auto concatenation = concatenate(first, second);
    

    If the vectors are likely to be very large (or contain elements that are expensive to copy), then you might need to do a reserve first to save reallocations:

    std::vector<int> concatenate(const std::vector<int>& lhs, const std::vector<int>& rhs)
    {
        std::vector<int> result;
        result.reserve( lhs.size() + rhs.size() );
        std::copy( lhs.begin(), lhs.end(), std::back_inserter(result) );
        std::copy( rhs.begin(), rhs.end(), std::back_inserter(result) );
        return result;
    }
    

    (Personally, I would only bother if there was evidence it was a bottleneck).

    0 讨论(0)
  • 2021-01-12 23:26

    No, it's not possible if you require that

    • no helper function is defined, and
    • the resulting vector can be declared const.
    0 讨论(0)
  • 2021-01-12 23:26
    class Vector : public vector<int>
    {
    public:
        Vector operator+(const Vector& vec);
    };
    
    Vector Vector::operator+(const Vector& vec)
    {
        for (int i = 0; i < vec.size(); i++)
        {
            this->push_back(vec[i]);
        }
    
        return *this;
    }
    
    0 讨论(0)
  • 2021-01-12 23:30

    Let me preface this by saying this is a hack, and will not give an answer to how to do this using a vector. Instead we'll depend on sizeof(int) == sizeof(char32_t) and use a u32string to contain our data.

    This answer makes it exceedingly clear that only primitives can be used in a basic_string, and that any primitive larger than 32-bits would require writing a custom char_traits, but for an int we can just use u32string.

    The qualification for this can be validated by doing:

    static_assert(sizeof(int) == sizeof(char32_t));
    

    Once size equality has been established, and with the knowledge that things like non-const data, and emplace or emplace_back cannot be used, u32string can be used like a vector<int>, with the notable inclusion of an addition opperator:

    const vector<int> first = {13};
    const vector<int> second = {42};
    const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());
    

    [Live Example]

    0 讨论(0)
  • 2021-01-12 23:32
    template<typename T>
    std::vector<T> operator+(const std::vector<T>& v1, const std::vector<T>& v2){
        std::vector<T> vr(std::begin(v1), std::end(v1));
        vr.insert(std::end(vr), std::begin(v2), std::end(v2));
        return vr;
    }
    

    This does require a helper "function", but at least it allows you to use it as

    const vector<int> concatenation = first + second;
    
    0 讨论(0)
提交回复
热议问题