การต่อสอง std :: เวกเตอร์


687

ฉันจะต่อสองstd::vectors เข้าด้วยกันได้อย่างไร


5
คำตอบที่ให้มาไม่ได้เรียงกันจริง ๆ พวกเขาต่อท้ายสำเนา อาจมีการใช้ (สำหรับมุมมองของประสิทธิภาพ) เพื่อสร้าง std :: vector concatenate method แต่มันจะต้องมีการแบ่งปันที่ซับซ้อนของการจัดการโหนดและนั่นอาจเป็นสาเหตุที่มันไม่ได้ทำ
FauChristian

8
@FauChristian: ไม่อาจไม่มีประโยชน์จากมุมมองของประสิทธิภาพ หน่วยความจำแบบเวกเตอร์ต้องต่อเนื่องดังนั้นสิ่งที่คุณแนะนำจึงเป็นไปไม่ได้ หากคุณต้องการ "การแบ่งปันการจัดการโหนดอย่างซับซ้อน" และหากคุณต้องการเปลี่ยนคลาสเวกเตอร์ในลักษณะใดคุณจะต้องจบด้วย deque ถึงอย่างนั้นมันก็เป็นเรื่องยากมากที่จะนำหน่วยความจำกลับมาใช้ใหม่ตามวิธีที่แนะนำแม้ว่ามันจะเริ่มเป็นไปได้มากขึ้น ฉันไม่คิดว่าจะมีการใช้งานในปัจจุบัน สิ่งสำคัญคือในการแบ่งปันโหนดการจัดการ (deque) โหนดปลายทางอาจว่างเปล่าบางส่วน
คุกกี้

4
@lecaruyer คุณรู้ว่าคุณทำเครื่องหมายคำถามที่ถูกถามสองปีก่อนเป็นที่ซ้ำกัน
eshirima

9
ฉันเพียงคนเดียวที่สงสัยว่าทำไมนี้ไม่ได้ถูกนำมาใช้เป็นa + bหรือa.concat(b)ในห้องสมุดมาตรฐาน? บางทีการใช้งานเริ่มต้นอาจไม่ดีนัก แต่การต่อข้อมูลอาเรย์ทุกอันไม่จำเป็นต้องปรับให้เหมาะสมขนาดเล็ก
oseiskar

9
ปีแห่งการวิวัฒนาการผู้ปฏิบัติงานมากเกินไปของภาษากระแสหลักใด ๆ ระบบ templating ที่เพิ่มความซับซ้อนของภาษาเป็นสองเท่า แต่คำตอบคือ v = v1 + v2
Spike0xff

คำตอบ:


728
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );

53
ฉันแค่เพิ่มโค้ดเพื่อรับจำนวนองค์ประกอบที่แต่ละเวกเตอร์ถือไว้และตั้งค่า vector1 ให้เป็นองค์ประกอบที่ยิ่งใหญ่ หากคุณไม่เช่นนั้นคุณกำลังทำสำเนาจำนวนมากโดยไม่จำเป็น
Joe Pineda

34
ฉันมีคำถาม. มันจะใช้ได้ไหมถ้า vector1 และ vector2 เป็นเวกเตอร์เดียวกันหรือไม่?
Alexander Rafferty

6
หากคุณต่อเวกเตอร์หลายตัวเข้าด้วยกันคุณควรโทรหาreserveเวกเตอร์ปลายทางก่อนหรือไม่
Faheem Mitha

33
@AlexanderRafferty: vector1.capacity() >= 2 * vector1.size()เฉพาะในกรณีที่ ซึ่งผิดปกติเว้นแต่คุณจะโทรstd::vector::reserve()หา ไม่เช่นนั้นเวกเตอร์จะทำการจัดสรรซ้ำการทำให้ตัววนซ้ำผ่านไปเป็นพารามิเตอร์ 2 และ 3
Drew Dormann

28
มันแย่มากที่ไม่มีนิพจน์รวบรัดในไลบรารีมาตรฐาน .concatหรือ+=อะไรบางอย่าง
nmr

193

หากคุณใช้ C ++ 11 และต้องการย้ายองค์ประกอบแทนที่จะคัดลอกพวกเขาคุณสามารถใช้std::move_iteratorพร้อมกับแทรก (หรือคัดลอก):

#include <vector>
#include <iostream>
#include <iterator>

int main(int argc, char** argv) {
  std::vector<int> dest{1,2,3,4,5};
  std::vector<int> src{6,7,8,9,10};

  // Move elements from src to dest.
  // src is left in undefined but safe-to-destruct state.
  dest.insert(
      dest.end(),
      std::make_move_iterator(src.begin()),
      std::make_move_iterator(src.end())
    );

  // Print out concatenated vector.
  std::copy(
      dest.begin(),
      dest.end(),
      std::ostream_iterator<int>(std::cout, "\n")
    );

  return 0;
}

สิ่งนี้จะไม่มีประสิทธิภาพมากขึ้นสำหรับตัวอย่างที่มี ints เนื่องจากการย้ายนั้นไม่มีประสิทธิภาพมากกว่าการคัดลอก แต่สำหรับโครงสร้างข้อมูลที่มีการย้ายที่ดีที่สุดจะสามารถหลีกเลี่ยงการคัดลอกสถานะที่ไม่จำเป็น:

#include <vector>
#include <iostream>
#include <iterator>

int main(int argc, char** argv) {
  std::vector<std::vector<int>> dest{{1,2,3,4,5}, {3,4}};
  std::vector<std::vector<int>> src{{6,7,8,9,10}};

  // Move elements from src to dest.
  // src is left in undefined but safe-to-destruct state.
  dest.insert(
      dest.end(),
      std::make_move_iterator(src.begin()),
      std::make_move_iterator(src.end())
    );

  return 0;
}

หลังจากการย้ายองค์ประกอบของ src ถูกปล่อยให้อยู่ในสถานะที่ไม่ได้กำหนด แต่ปลอดภัยต่อการทำลายล้างและองค์ประกอบเดิมของมันจะถูกถ่ายโอนโดยตรงไปยังองค์ประกอบใหม่ของปลายทางในตอนท้าย


6
std :: make_move_iterator () วิธีการช่วยฉันเมื่อพยายามเชื่อม std :: vectors ของ std :: unique_ptr
Knitschi

ความแตกต่างระหว่างสิ่งนี้กับstd::move(src.begin(), src.end(), back_inserter(dest))อะไร?
kshenoy


77

หรือคุณสามารถใช้:

std::copy(source.begin(), source.end(), std::back_inserter(destination));

รูปแบบนี้มีประโยชน์หากสองเวกเตอร์ไม่มีสิ่งเดียวกันประเภทเดียวกันเนื่องจากคุณสามารถใช้บางสิ่งแทน std :: back_inserter เพื่อแปลงจากประเภทหนึ่งไปเป็นอีกประเภทหนึ่ง


7
วิธีการคัดลอกไม่ใช่วิธีที่ดี มันจะเรียก push_back หลาย ๆ ครั้งซึ่งหมายความว่าหากต้องใส่องค์ประกอบจำนวนมากสิ่งนี้อาจหมายถึงการจัดสรรหลายครั้ง มันเป็นการดีกว่าที่จะใช้การแทรกเนื่องจากการใช้เวกเตอร์สามารถเพิ่มประสิทธิภาพบางอย่างเพื่อหลีกเลี่ยงการจัดสรรใหม่ มันสามารถจองหน่วยความจำก่อนที่จะเริ่มการคัดลอก
Yogesh Arora

7
@Yogesh: ได้รับ แต่ไม่มีอะไรหยุดคุณโทรreserveก่อน เหตุผลที่บางครั้งก็เป็นประโยชน์คือถ้าคุณต้องการที่จะใช้สิ่งอื่นที่ไม่ใช่std::copy back_inserter
Roger Lipscombe

เมื่อคุณพูดว่า "การจัดสรรหลายรายการ" นั่นเป็นจริง - แต่จำนวนการจัดสรรนั้นอยู่ในบันทึกที่แย่ที่สุด (จำนวนรายการที่เพิ่ม) - ซึ่งหมายความว่าค่าใช้จ่ายในการเพิ่มรายการนั้นคงที่ในจำนวนรายการที่เพิ่มขึ้น (โดยทั่วไปไม่ต้องกังวลเกี่ยวกับมันยกเว้นว่าโปรไฟล์จะแสดงว่าคุณต้องมีการจอง)
Martin Bonner สนับสนุน Monica

คุณอาจต้องการใช้ std :: transform เพื่อทำสิ่งนี้แทน
Martin Broadhurst

1
คัดลอกดูดมากแม้จะมีการสำรอง เวกเตอร์ :: ส่วนแทรกจะหลีกเลี่ยงการตรวจสอบทั้งหมด: quick-bench.com/bLJO4OfkAzMcWia7Pa80ynwmAIA
Denis Yaroshevskiy

63

ด้วย C ++ 11 ฉันต้องการที่จะต่อท้ายเวกเตอร์ b กับ a:

std::move(b.begin(), b.end(), std::back_inserter(a));

เมื่อใดaและbจะไม่ทับซ้อนกันและbจะไม่ถูกใช้อีกต่อไป


นี่คือstd::moveจาก<algorithm>ที่ไม่ปกติ จากstd::move<utility>


10
พฤติกรรมที่ไม่ได้กำหนดถ้า a คือ b (ซึ่งก็โอเคถ้าคุณรู้ว่ามันไม่มีทางเกิดขึ้นได้ แต่ควรรู้ไว้ในโค้ดวัตถุประสงค์ทั่วไป)
Martin Bonner สนับสนุน Monica

1
@ มาร์ตินโบนเนอร์ขอบคุณที่พูดถึงมัน อาจเป็นไปได้ว่าฉันควรกลับไปใช้insertวิธีเดิมซึ่งปลอดภัยกว่า
Deqing

15
Ah, OTHER std :: move ค่อนข้างสับสนในครั้งแรกที่คุณเห็นมัน
xaxxon

1
สิ่งนี้แตกต่างจากinsert()กับmove_iterators หรือไม่? ถ้าเป็นเช่นนั้นได้อย่างไร
GPhilo

1
ฉันได้เพิ่มบันทึกเกี่ยวกับสิ่งที่std::moveเรากำลังพูดถึงที่นี่เนื่องจากคนส่วนใหญ่ไม่ทราบว่าเกินพิกัดนี้ หวังว่ามันจะเป็นการปรับปรุง
YSC


24

ฉันชอบหนึ่งที่กล่าวถึงแล้ว:

a.insert(a.end(), b.begin(), b.end());

แต่ถ้าคุณใช้ C ++ 11 มีวิธีทั่วไปมากกว่าหนึ่งวิธี:

a.insert(std::end(a), std::begin(b), std::end(b));

นอกจากนี้ไม่ใช่ส่วนหนึ่งของคำถาม แต่แนะนำให้ใช้reserveก่อนที่จะผนวกเพื่อประสิทธิภาพที่ดีขึ้น reserveและถ้าคุณกำลังเชื่อมโยงเวกเตอร์ด้วยตัวเองโดยไม่ต้องสำรองมันล้มเหลวดังนั้นคุณควร


ดังนั้นโดยทั่วไปสิ่งที่คุณต้องการ:

template <typename T>
void Append(std::vector<T>& a, const std::vector<T>& b)
{
    a.reserve(a.size() + b.size());
    a.insert(a.end(), b.begin(), b.end());
}

2
std::จะอนุมานได้ผ่านการค้นหาโต้แย้งขึ้นอยู่กับ end(a)จะเพียงพอ
Asu

4
@Asu ADL จะเพิ่มก็ต่อstd::เมื่อประเภทaมาจากstdซึ่งเอาชนะด้านทั่วไป
Potatoswatter

จุดดี. ในกรณีนี้มันเป็นเวคเตอร์ดังนั้นมันจะทำงานได้ แต่ก็ใช่ว่าจะเป็นทางออกที่ดีกว่า
Asu

std :: start () / end () ถูกเพิ่มสำหรับคอลเลกชัน (เช่นอาร์เรย์) ซึ่งไม่มีฟังก์ชันเหล่านี้เป็นสมาชิก แต่อาร์เรย์ยังไม่มีฟังก์ชันสมาชิก insert () และเรียกคำถามว่า "มีคอลเลกชันที่มีการแทรก () แต่ไม่มี start () (ซึ่งทำงานกับ std :: start ()) หรือไม่"
James Curran



9

เพิ่มประสิทธิภาพการทำงานทั่วไปสำหรับ concatenate คือการตรวจสอบขนาดของเวกเตอร์ที่ และผสาน / แทรกอันที่เล็กกว่าด้วยอันที่ใหญ่กว่า

//vector<int> v1,v2;
if(v1.size()>v2.size()) {
    v1.insert(v1.end(),v2.begin(),v2.end());
} else {
    v2.insert(v2.end(),v1.begin(),v1.end());
}

เรียบง่าย แต่ฉันไม่เคยคิดแบบนั้น!
Zimano

2
รหัสตัวอย่างไม่ถูกต้อง v1.insert(v2.end()...กำลังใช้ iterator เข้าไปเพื่อระบุตำแหน่งในv2 v1
David Stone

คุณยังสามารถใช้การสลับอย่างรวดเร็ว @DavidStone ฉันแก้ไขเพื่อให้คำสั่ง concat อาจมีการเปลี่ยนแปลง เป็นไปได้หรือไม่ที่จะเพิ่มไปยังจุดเริ่มต้นของเวกเตอร์
qwr

คุณสามารถแทรกลงในจุดเริ่มต้น แต่นั่นจะช้าลง อย่างไรก็ตามในการ "เรียงต่อกัน" อย่างแท้จริงคำสั่งซื้อมักจะมีความสำคัญดังนั้นนั่นคือสิ่งที่คุณต้องทำ
David Stone

7

หากคุณต้องการให้เวกเตอร์เรียงต่อกันอย่างกระชับคุณสามารถโอเวอร์โหลด+=โอเปอเรเตอร์ได้

template <typename T>
std::vector<T>& operator +=(std::vector<T>& vector1, const std::vector<T>& vector2) {
    vector1.insert(vector1.end(), vector2.begin(), vector2.end());
    return vector1;
}

จากนั้นคุณสามารถเรียกมันว่า:

vector1 += vector2;

6

หากคุณสนใจในการรับประกันข้อยกเว้นที่แข็งแกร่ง (เมื่อตัวสร้างสำเนาสามารถโยนข้อยกเว้น):

template<typename T>
inline void append_copy(std::vector<T>& v1, const std::vector<T>& v2)
{
    const auto orig_v1_size = v1.size();
    v1.reserve(orig_v1_size + v2.size());
    try
    {
        v1.insert(v1.end(), v2.begin(), v2.end());
    }
    catch(...)
    {
        v1.erase(v1.begin() + orig_v1_size, v1.end());
        throw;
    }
}

append_moveโดยทั่วไปแล้วจะไม่สามารถนำไปใช้กับการรับประกันที่คล้ายกันได้หากตัวสร้างการเคลื่อนไหวขององค์ประกอบเวกเตอร์สามารถโยนได้ (ซึ่งไม่น่าเป็นไปได้ แต่ยังคงมีอยู่)


เป็นไปไม่ได้ที่v1.erase(...จะโยนด้วยหรือไม่
Class Skeleton

insertจัดการเรื่องนี้ได้แล้ว นอกจากนี้สายนี้จะเทียบเท่ากับerase resize
Potatoswatter

ฉันชอบสิ่งนี้ - ขอบคุณ!
natersoz

5

เพิ่มอันนี้ลงในไฟล์ส่วนหัวของคุณ:

template <typename T> vector<T> concat(vector<T> &a, vector<T> &b) {
    vector<T> ret = vector<T>();
    copy(a.begin(), a.end(), back_inserter(ret));
    copy(b.begin(), b.end(), back_inserter(ret));
    return ret;
}

และใช้วิธีนี้:

vector<int> a = vector<int>();
vector<int> b = vector<int>();

a.push_back(1);
a.push_back(2);
b.push_back(62);

vector<int> r = concat(a, b);

r จะมี [1,2,62]


ไม่ทราบว่าทำไมสิ่งนี้ถึงถูกโหวต อาจไม่ใช่วิธีที่มีประสิทธิภาพที่สุดในการทำเช่นนี้ แต่ก็ไม่ผิดและมีประสิทธิภาพ
leeor_net

4

ต่อไปนี้เป็นโซลูชันสำหรับวัตถุประสงค์ทั่วไปโดยใช้ซีแมนติกซ์การย้าย C ++ 11

template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, const std::vector<T>& rhs)
{
    if (lhs.empty()) return rhs;
    if (rhs.empty()) return lhs;
    std::vector<T> result {};
    result.reserve(lhs.size() + rhs.size());
    result.insert(result.cend(), lhs.cbegin(), lhs.cend());
    result.insert(result.cend(), rhs.cbegin(), rhs.cend());
    return result;
}

template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, const std::vector<T>& rhs)
{
    lhs.insert(lhs.cend(), rhs.cbegin(), rhs.cend());
    return std::move(lhs);
}

template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, std::vector<T>&& rhs)
{
    rhs.insert(rhs.cbegin(), lhs.cbegin(), lhs.cend());
    return std::move(rhs);
}

template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, std::vector<T>&& rhs)
{
    if (lhs.empty()) return std::move(rhs);
    lhs.insert(lhs.cend(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
    return std::move(lhs);
}

หมายเหตุวิธีการที่แตกต่างจากไอเอ็นจีไปยังappendvector


4

คุณสามารถเตรียมเทมเพลตของคุณเองสำหรับ + ​​โอเปอเรเตอร์:

template <typename T> 
inline T operator+(const T & a, const T & b)
{
    T res = a;
    res.insert(res.end(), b.begin(), b.end());
    return res;
}

สิ่งต่อไป - ใช้ +:

vector<int> a{1, 2, 3, 4};
vector<int> b{5, 6, 7, 8};
for (auto x: a + b)
    cout << x << " ";
cout << endl;

ตัวอย่างนี้ให้เอาต์พุต:

1 2 3 4 5 6 7 8

3
ใช้เป็นอันตรายมันจะดีกว่าที่จะใช้T operator+(const T & a, const T & b) vector<T> operator+(const vector<T> & a, const vector<T> & b)
Matthieu H

4

มีอัลกอริทึมstd::mergeจากC ++ 17ซึ่งใช้งานง่ายมาก

ด้านล่างเป็นตัวอย่าง:

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

int main()
{
    //DATA
    std::vector<int> v1{2,4,6,8};
    std::vector<int> v2{12,14,16,18};

    //MERGE
    std::vector<int> dst;
    std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst));

    //PRINT
    for(auto item:dst)
        std::cout<<item<<" ";

    return 0;
}

3
ฉันไม่คิดว่ามันจะใช้งานง่ายไปกว่าstd::vector::insertนี้ แต่ทำเพื่อสิ่งที่แตกต่าง: ผสานสองช่วงเป็นช่วงใหม่กับการแทรกเวกเตอร์หนึ่งตัวที่ส่วนท้ายของอีกอัน ควรพูดถึงคำตอบไหม?
jb

4

หากเป้าหมายของคุณคือทำซ้ำในช่วงของค่าเพื่อวัตถุประสงค์ในการอ่านอย่างเดียวทางเลือกก็คือการห่อเวกเตอร์ทั้งสองรอบพร็อกซี (O (1)) แทนการคัดลอก (O (n)) ดังนั้นพวกเขาจะเห็นทันที เป็นหนึ่งเดียวที่ต่อเนื่องกัน

std::vector<int> A{ 1, 2, 3, 4, 5};
std::vector<int> B{ 10, 20, 30 };

VecProxy<int> AB(A, B);  // ----> O(1)!

for (size_t i = 0; i < AB.size(); i++)
    std::cout << AB[i] << " ";  // ----> 1 2 3 4 5 10 20 30

อ้างถึงhttps://stackoverflow.com/a/55838758/2379625สำหรับรายละเอียดเพิ่มเติมรวมถึงการใช้งาน 'VecProxy' เช่นเดียวกับข้อดีข้อเสีย


3
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));

6
แม้ว่าข้อมูลโค้ดนี้อาจช่วยแก้ปัญหาได้ แต่ก็ไม่ได้อธิบายว่าทำไมหรือตอบคำถามอย่างไร โปรดระบุคำอธิบายสำหรับรหัสของคุณเนื่องจากช่วยปรับปรุงคุณภาพการโพสต์ของคุณได้อย่างแท้จริง ผู้ตั้งค่าสถานะ / ผู้ตรวจทาน: สำหรับคำตอบที่ใช้รหัสอย่างเช่น downvote อย่าลบ! (หมายเหตุ: คำตอบนี้อาจง่ายพอที่จะทำให้คำอธิบายและไม่จำเป็นต้อง downvotes คุณอาจต้องการเพิ่มคำอธิบายเพื่อป้องกันการตั้งค่าสถานะ NAA / VLQ เพิ่มเติม)
Scott Weldon

2

ฉันได้ใช้ฟังก์ชั่นนี้ซึ่งเชื่อมต่อจำนวนของคอนเทนเนอร์ใด ๆ ย้ายจากการอ้างอิง rvalue และการคัดลอกเป็นอย่างอื่น

namespace internal {

// Implementation detail of Concatenate, appends to a pre-reserved vector, copying or moving if
// appropriate
template<typename Target, typename Head, typename... Tail>
void AppendNoReserve(Target* target, Head&& head, Tail&&... tail) {
    // Currently, require each homogenous inputs. If there is demand, we could probably implement a
    // version that outputs a vector whose value_type is the common_type of all the containers
    // passed to it, and call it ConvertingConcatenate.
    static_assert(
            std::is_same_v<
                    typename std::decay_t<Target>::value_type,
                    typename std::decay_t<Head>::value_type>,
            "Concatenate requires each container passed to it to have the same value_type");
    if constexpr (std::is_lvalue_reference_v<Head>) {
        std::copy(head.begin(), head.end(), std::back_inserter(*target));
    } else {
        std::move(head.begin(), head.end(), std::back_inserter(*target));
    }
    if constexpr (sizeof...(Tail) > 0) {
        AppendNoReserve(target, std::forward<Tail>(tail)...);
    }
}

template<typename Head, typename... Tail>
size_t TotalSize(const Head& head, const Tail&... tail) {
    if constexpr (sizeof...(Tail) > 0) {
        return head.size() + TotalSize(tail...);
    } else {
        return head.size();
    }
}

}  // namespace internal

/// Concatenate the provided containers into a single vector. Moves from rvalue references, copies
/// otherwise.
template<typename Head, typename... Tail>
auto Concatenate(Head&& head, Tail&&... tail) {
    size_t totalSize = internal::TotalSize(head, tail...);
    std::vector<typename std::decay_t<Head>::value_type> result;
    result.reserve(totalSize);
    internal::AppendNoReserve(&result, std::forward<Head>(head), std::forward<Tail>(tail)...);
    return result;
}

1

หากสิ่งที่คุณกำลังมองหาเป็นวิธีที่จะเพิ่มเวกเตอร์ไปยังอีกหลังจากการสร้างvector::insertเป็นทางออกที่ดีที่สุดของคุณเช่นที่ได้รับคำตอบหลายครั้งเช่น:

vector<int> first = {13};
const vector<int> second = {42};

first.insert(first.end(), second.cbegin(), second.cend());

น่าเศร้าที่มีวิธีการสร้างไม่เป็นแล้วคุณจะต้องสร้างแล้วconst vector<int>insert


หากสิ่งที่คุณกำลังมองหาคือที่เก็บของที่มีการต่อกันของสองตัวนี้vector<int>อาจมีสิ่งที่ดีกว่าสำหรับคุณถ้า:

  1. คุณvectorมีพื้นฐาน
  2. primitives ที่คุณมีอยู่มีขนาด 32 บิตหรือเล็กกว่า
  3. คุณต้องการconstตู้คอนเทนเนอร์

ถ้าข้างต้นเป็นความจริงทุกประการผมขอแนะนำให้ใช้basic_stringผู้ที่ตรงกับขนาดของดั้งเดิมที่มีอยู่ในของคุณchar_type vectorคุณควรรวมstatic_assertรหัสในการตรวจสอบขนาดเหล่านี้ให้สอดคล้องกัน:

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

ด้วยการถือครองที่แท้จริงนี้คุณสามารถทำได้:

const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับความแตกต่างระหว่างstringและvectorคุณสามารถดูได้ที่นี่: https://stackoverflow.com/a/35558008/2642059

สำหรับตัวอย่างสดของรหัสนี้คุณสามารถดูได้ที่นี่: http://ideone.com/7Iww3I


0

วิธีแก้ปัญหานี้อาจซับซ้อนเล็กน้อย แต่ก็boost-rangeมีสิ่งที่ดีอื่น ๆ

#include <iostream>
#include <vector>
#include <boost/range/algorithm/copy.hpp>

int main(int, char**) {
    std::vector<int> a = { 1,2,3 };
    std::vector<int> b = { 4,5,6 };
    boost::copy(b, std::back_inserter(a));
    for (auto& iter : a) {
        std::cout << iter << " ";
    }
    return EXIT_SUCCESS;
}

บ่อยครั้งที่คนตั้งใจจะรวมเวกเตอร์aและวนbซ้ำมันจะทำการดำเนินการบางอย่าง ในกรณีนี้มีjoinฟังก์ชั่นที่เรียบง่ายไร้สาระ

#include <iostream>
#include <vector>
#include <boost/range/join.hpp>
#include <boost/range/algorithm/copy.hpp>

int main(int, char**) {
    std::vector<int> a = { 1,2,3 };
    std::vector<int> b = { 4,5,6 };
    std::vector<int> c = { 7,8,9 };
    // Just creates an iterator
    for (auto& iter : boost::join(a, boost::join(b, c))) {
        std::cout << iter << " ";
    }
    std::cout << "\n";
    // Can also be used to create a copy
    std::vector<int> d;
    boost::copy(boost::join(a, boost::join(b, c)), std::back_inserter(d));
    for (auto& iter : d) {
        std::cout << iter << " ";
    }
    return EXIT_SUCCESS;
}

สำหรับเวกเตอร์ขนาดใหญ่นี่อาจเป็นข้อได้เปรียบเนื่องจากไม่มีการคัดลอก นอกจากนี้ยังสามารถใช้สำหรับการทำสำเนา generalizes ไปยังคอนเทนเนอร์มากกว่าหนึ่งคอนเทนเนอร์ได้อย่างง่ายดาย

ด้วยเหตุผลบางอย่างไม่มีอะไรเหมือนboost::join(a,b,c)ซึ่งอาจสมเหตุสมผล


0

คุณสามารถทำได้ด้วยอัลกอริธึม STL ที่นำไปใช้ล่วงหน้าโดยใช้เทมเพลตสำหรับการใช้งานประเภท polymorphic

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

template<typename T>

void concat(std::vector<T>& valuesa, std::vector<T>& valuesb){

     for_each(valuesb.begin(), valuesb.end(), [&](int value){ valuesa.push_back(value);});
}

int main()
{
    std::vector<int> values_p={1,2,3,4,5};
    std::vector<int> values_s={6,7};

   concat(values_p, values_s);

    for(auto& it : values_p){

        std::cout<<it<<std::endl;
    }

    return 0;
}

คุณสามารถล้างเวกเตอร์ที่สองหากคุณไม่ต้องการใช้เพิ่มเติม ( clear()วิธีการ)


0

Concatenate สองstd::vector-sกับวงในforstd::vector

ตัวอย่าง:

std::vector <int> v1 {1, 2, 3};//declare vector1
std::vector <int> v2 {4, 5};//declare vector2
std::vector <int> suma;//declare vector suma

for(int i = 0; i < v1.size()-1;i++)//for loop 1
{
     suma.push_back(v1[i]);
}

for(int i = 0; i< v2.size()-1;i++)/for loop 2
{
     suma.push_back(v2[i]);
}

for(int i = 0; i < suma.size(); i++)//for loop 3-output
{
     std::cout<<suma[i];
}

main()เขียนโค้ดนี้ใน


คุณforลูปผิด ดัชนีที่ถูกต้องในเวกเตอร์จาก 0 size()-1ถึง คุณเงื่อนไขการเลิกห่วงจะต้องi < v1.size()ใช้ไม่ได้< <=การใช้เงื่อนไขที่ไม่ถูกต้องเข้าถึงหน่วยความจำภายนอกคอนเทนเนอร์
Blastfurnace

นอกจากจะใช้งานไม่ได้แล้วรหัสนี้ก็ไม่มีความหมายอะไรมาก อย่างน้อยคุณควรใช้ตัวautoวนซ้ำแทนการสร้างดัชนีด้วยตนเอง คุณไม่แคร์ว่าดัชนีใดที่คุณต่อกันเท่านั้นที่จะเรียงตามลำดับ
Tarick Welling

คุณช่วยอธิบายได้ไหมว่าทำไมคุณถึงใช้size()-1ในสภาวะวนรอบสองแบบ? นั่นข้ามองค์ประกอบเวกเตอร์สุดท้าย วงที่สามเป็นวงเดียวที่ถูกต้องในตอนนี้
Blastfurnace

-3

ตามจริงแล้วคุณสามารถต่อเวกเตอร์สองตัวเข้าด้วยกันโดยคัดลอกองค์ประกอบจากเวกเตอร์สองตัวไปอีกอันหนึ่งหรือเพียงแค่ผนวกหนึ่งในสองเวกเตอร์! มันขึ้นอยู่กับเป้าหมายของคุณ

วิธีที่ 1:กำหนดขนาดเวกเตอร์ใหม่ด้วยผลรวมของขนาดเวกเตอร์ดั้งเดิมสองขนาด

vector<int> concat_vector = vector<int>();
concat_vector.setcapacity(vector_A.size() + vector_B.size());
// Loop for copy elements in two vectors into concat_vector

วิธีที่ 2:ผนวกเวกเตอร์ A โดยการเพิ่ม / แทรกองค์ประกอบของเวกเตอร์ B

// Loop for insert elements of vector_B into vector_A with insert() 
function: vector_A.insert(vector_A .end(), vector_B.cbegin(), vector_B.cend());

4
คำตอบของคุณเพิ่มอะไรที่ยังไม่ได้ระบุไว้ในคำตอบอื่น ๆ ?
Mat

13
@Mat: ตัวหนา
marcv81

หากไม่ต้องการใช้เวกเตอร์ดั้งเดิมอีกต่อไปอาจเป็นการดีกว่าที่จะใช้std::move_iteratorเพื่อย้ายองค์ประกอบแทนที่จะคัดลอก (ดูen.cppreference.com/w/cpp/iterator/move_iterator )
tmlen

คือsetcapacityอะไร คือfunction: อะไร
LF

@LF ฉันคิดว่าเขากำลังพูดถึงresizeวิธีการ
Matthieu H
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.