تجميع اثنين من الأمراض المنقولة جنسيا :: ناقلات

كيف أقوم بتوصيل اثنين std :: vector

469
lecaruyer أنت تدرك أنك وضعت علامة على سؤال تم طرحه قبل عامين على أنه نسخة طبق الأصل
وأضاف المؤلف eshirima, مصدر
FauChristian: لا ، قد لا يكون هناك استخدام من وجهة نظر الكفاءة. يجب أن تكون ذاكرة متجهة مستمرة ، لذا فإن ما اقترحته مستحيل. إذا كنت تريد "مشاركة متطورة لإدارة العقد" ، وإذا كنت تريد تغيير فئة المتجه بهذه الطريقة ، فسوف ينتهي بك الأمر مع deque. حتى في هذه الحالة ، من الصعب للغاية إعادة استخدام الذاكرة بالطريقة المقترحة ، على الرغم من أن ذلك سيصبح أكثر جدوى. لا أعتقد أنه يتم تنفيذه حاليا. الشيء الرئيسي هو أنه في مثل هذه المشاركة في عقد الإدارة (deque) قد تكون عقدة النهاية فارغة جزئيًا.
وأضاف المؤلف Cookie, مصدر
الإجابات المقدمة لا تتسلسل بالفعل. انهم تذييل نسخة. قد يكون هناك استخدام (من وجهة نظر الكفاءة) لإنشاء طريقة متسلسلة std :: vector concatenate ، إلا أنها تتطلب بعض المشاركة المعقدة لإدارة العقد وهذا هو السبب على الأرجح في عدم إنجازها.
وأضاف المؤلف FauChristian, مصدر
هل أنا الوحيد الذي يتساءل عن سبب عدم تنفيذ ذلك كـ a + b أو a.concat (b) في المكتبة القياسية؟ ربما يكون التطبيق الافتراضي دون المستوى الأمثل ، ولكن لا تحتاج كل سلسلة صفيف إلى أن تكون محسنة بشكل دقيق
وأضاف المؤلف oseiskar, مصدر

16 إجابة

vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
531
وأضاف
إذا كان لديك متصلاً لعدة متجهات إلى واحد ، فهل من المفيد استدعاء Reserve على ناقل الوجهة أولاً؟
وأضاف المؤلف Faheem Mitha, مصدر
@ أيدين أراه. شكرا على التوضيح.
وأضاف المؤلف Faheem Mitha, مصدر
@ Khaur: هذا مرعب إلى النقطة التي يصعب تصديقها. إنه لأمر غاية في الأهمية بالنسبة للتنفيذ للكشف عن التكرارات هي الوصول العشوائي ، وحساب الحجم ، وحجز المساحة المطلوبة مسبقًا. أعتقد أن MSFT حتى يفعل ذلك للمثقفين إلى الأمام.
وأضاف المؤلف Mooing Duck, مصدر
AlexanderRafferty: فقط إذا كان vector1.capacity ()> = 2 * vector1.size() . وهو أمر غير نمطي إلا إذا اتصلت std :: vector :: reserve() . وإلا فسيتم إعادة تخصيص المتجه ، مما يؤدي إلى إبطال عمل المكررات التي تم تمريرها كمعلمين 2 و 3.
وأضاف المؤلف Drew Dormann, مصدر
عندي سؤال. هل سيعمل هذا إذا كان vector1 و vector2 متشابهين؟
وأضاف المؤلف Alexander Rafferty, مصدر
فما استقاموا لكم فاستقيموا فقط إضافة رمز لأول الحصول على عدد العناصر التي يحمل كل ناقلات ، وتعيين vector1 ليكون واحد يحمل أكبر. إذا كنت تفعل خلاف ذلك كنت تفعل الكثير من النسخ غير الضرورية.
وأضاف المؤلف Joe Pineda, مصدر
إنه أمر سيء للغاية ليس هناك تعبير أكثر إيجازًا في المكتبة القياسية. .concat أو + = أو شيء ما
وأضاف المؤلف nmr, مصدر
FaheemMitha: نظرًا لأن وسيطات insert هي متجهات ، فإنها تعرف بالفعل عدد العناصر التي تنتظرها وسوف تتعامل معها بنفسها. إذا كنا نقوم بإدخال أشياء أخرى مثل الصفيف ، كان من المفيد حجز المساحة أولاً.
وأضاف المؤلف Aidin, مصدر
MooingDuck أنت محق ، فاتتني المرسل واعتقدت أن نسخة المدخلات المدخلة مطبقة لجميع أنواع التكرارات. النسخة المُحَوِّلة لإعادة التوجيه تعمل الكثير من الأشياء. شكرًا جزيلاً للإشارة إلى ذلك ، لقد حذفت تعليقي الأولي بحيث لا يظهر بدون تعليقك.
وأضاف المؤلف Khaur, مصدر

أود استخدام وظيفة الإدراج ، مثل:

vector a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
112
وأضاف

إذا كنت تستخدم C ++ 11 وترغب في نقل العناصر بدلاً من مجرد نسخها ، فيمكنك استخدام std :: move_iterator ( http://en.cppreference.com/w/cpp/iterator/move_iterator ) مع إدراج (أو نسخ):

#include 
#include 
#include 

int main(int argc, char** argv) {
  std::vector dest{1,2,3,4,5};
  std::vector 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(std::cout, "\n")
    );

  return 0;
}

لن يكون هذا أكثر فاعلية للمثال الذي يحتوي على ints ، نظرًا لأن نقلها ليس أكثر فعالية من نسخها ، ولكن بالنسبة إلى بنية البيانات مع التحركات المحسنة ، يمكنه تجنب نسخ الحالة غير الضرورية:

#include 
#include 
#include 

int main(int argc, char** argv) {
  std::vector> dest{{1,2,3,4,5}, {3,4}};
  std::vector> 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 في حالة غير محددة ولكن آمنة للتدمير ، وتم نقل عناصره السابقة مباشرة إلى عنصر dest الجديد في النهاية.

112
وأضاف
ساعدني الأسلوب std :: make_move_iterator() عند محاولة تسلسل std :: vectors من std :: unique_ptr.
وأضاف المؤلف Knitschi, مصدر

أو يمكنك استخدام:

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

يكون هذا النمط مفيدًا إذا كانت المتجهات لا تحتوي بالضبط على نفس نوع الشيء ، لأنه يمكنك استخدام شيء ما بدلاً من std :: back_inserter للتحويل من نوع إلى آخر.

70
وأضاف
@ Yogesh: منح ، ولكن لا يوجد شيء يمنعك من الاتصال احتياطي أولاً. يكون السبب std :: copy مفيدًا أحيانًا إذا كنت تريد استخدام شيء آخر غير back_inserter .
وأضاف المؤلف Roger Lipscombe, مصدر
عندما تقول "توزيعات متعددة" ، هذا صحيح - ولكن عدد عمليات التخصيص في سجل أسوأ (عدد الإدخالات المضافة) - مما يعني أن تكلفة إضافة إدخال ثابتة في عدد الإدخالات المضافة. (في الأساس ، لا تقلق حيال ذلك ما لم يظهر التنميط احتياطيًا).
وأضاف المؤلف Martin Bonner, مصدر
قد ترغب في استخدام std :: transform للقيام بذلك بدلاً من ذلك.
وأضاف المؤلف Martin Broadhurst, مصدر
طريقة النسخ ليست بهذه الطريقة الجيدة. سوف يستدعي push_back عدة مرات مما يعني أنه إذا كان يجب إدخال الكثير من العناصر ، فقد يعني ذلك إعادة تخصيص متعددة. من الأفضل استخدام الإدخال حيث يمكن لتنفيذ المتجه القيام ببعض التحسين لتجنب إعادة التخصيص. فإنه يمكن حجز الذاكرة قبل بدء النسخ
وأضاف المؤلف Yogesh Arora, مصدر
std::vector first;
std::vector second;

first.insert(first.end(), second.begin(), second.end());
30
وأضاف

مع C ++ 11 ، أفضّل اتباع تذييل b إلى a:

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

عندما لا يتم تراكب a و b ، ولن يتم استخدام b بعد الآن.

27
وأضاف
MartinBonner شكرًا على ذكر ذلك. ربما ينبغي أن أعود إلى القديم بطريقة أكثر أمانًا.
وأضاف المؤلف Deqing, مصدر
ما عليك سوى إضافة سطر عنوان التالي التالي: #include
وأضاف المؤلف Manohar Reddy Poreddy, مصدر
سلوك غير محدد إذا كان بالفعل b (وهو موافق إذا كنت تعرف أنه لا يمكن أن يحدث أبدًا - ولكنه يستحق أن يكون مدركًا في رمز الغرض العام).
وأضاف المؤلف Martin Bonner, مصدر
آه ، std :: move أخرى. مربك جدا في المرة الأولى التي تراها.
وأضاف المؤلف xaxxon, مصدر

انا افضل واحد ذكر بالفعل:

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

ولكن إذا كنت تستخدم C ++ 11 ، فهناك طريقة عامة أكثر:

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

أيضًا ، ليس جزءًا من سؤال ، ولكن يُنصح باستخدام احتياطي قبل إلحاقه بأداء أفضل. وإذا كنت متصلاً مع المتجه نفسه ، فبدون إخفائه ، عليك دائمًا حجز .


إذاً ما تحتاجه في الأساس:

template 
void Append(std::vector& a, const std::vector& b)
{
    a.reserve(a.size() + b.size());
    a.insert(a.end(), b.begin(), b.end());
}
18
وأضاف
سيضيفAsu ADL std :: فقط إذا كان نوع a يأتي من std ، والذي يهزم الجانب العام.
وأضاف المؤلف Potatoswatter, مصدر
يتم استنتاج std :: من خلال البحث المعتمد على الوسيطات . النهاية (أ) ستكون كافية.
وأضاف المؤلف Asu, مصدر
نقطة جيدة. في هذه الحالة ، إنه متجه لذلك سيعمل على أي حال ، لكن نعم هذا هو الحل الأفضل.
وأضاف المؤلف Asu, مصدر

يجب عليك استخدام vector :: insert

v1.insert(v1.end(), v2.begin(), v2.end());
5
وأضاف

إذا كنت مهتمًا بضمان الاستثناء القوي (عندما يستطيع مُنشئ النسخ إلقاء استثناء):

template
inline void append_copy(std::vector& v1, const std::vector& 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 مماثلة بشكل عام إذا كان من الممكن تنفيذ منشئ الحركة الخاص بعامل الموجه (وهو أمر غير محتمل ولكنه لا يزال).

4
وأضاف
insert يعالج هذا بالفعل. أيضا ، هذه المكالمة إلى مسح تعادل تغيير الحجم .
وأضاف المؤلف Potatoswatter, مصدر
هل من غير الممكن لـ v1.erase (... ) رمي أيضا؟
وأضاف المؤلف camelCase, مصدر
vector v1 = {1, 2, 3, 4, 5};
vector v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));
3
وأضاف
على الرغم من أن مقتطف الشفرة هذا قد يحل المشكلة ، إلا أنه لا يشرح لماذا أو كيف يجيب على السؤال. الرجاء تضمين شرح لرمزك ، لأن ذلك يساعد بالفعل في تحسين جودة مشاركتك. علماء المال/المراجعين: للحصول على إجابات للشفرة فقط مثل هذا واحد ، أسفل ، لا تحذف! (ملاحظة: قد تكون هذه الإجابة بسيطة بشكل كافٍ لتقديم تفسير ، ومن ثم ، downvotes ، غير ضرورية. قد لا تزال ترغب في إضافة شرح لمنع المزيد من علامات NAA/VLQ.)
وأضاف المؤلف Scott Weldon, مصدر

أضف هذا إلى ملف رأسك:

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

واستخدامها بهذه الطريقة:

vector a = vector();
vector b = vector();

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

vector r = concat(a, b);

ص سوف تحتوي على [1،2،62]

2
وأضاف
لا أعرف لماذا تم التصويت عليه. قد لا تكون الطريقة الأكثر فعالية للقيام بذلك ولكنها ليست خاطئة وفعالة.
وأضاف المؤلف leeor_net, مصدر

باستخدام النطاق v3 ، قد يكون لديك سلسلة كسولة :

ranges::view::concat(v1, v2)

Demo.

2
وأضاف

فيما يلي حل للأغراض العامة باستخدام دلالات الخطوة C ++ 11:

template 
std::vector concat(const std::vector& lhs, const std::vector& rhs)
{
    if (lhs.empty()) return rhs;
    if (rhs.empty()) return lhs;
    std::vector 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 
std::vector concat(std::vector&& lhs, const std::vector& rhs)
{
    lhs.insert(lhs.cend(), rhs.cbegin(), rhs.cend());
    return std::move(lhs);
}

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

template 
std::vector concat(std::vector&& lhs, std::vector&& 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);
}

لاحظ كيف يختلف هذا عن إلحاق إلى vector .

1
وأضاف

إذا كان ما تبحث عنه هو طريقة لإلحاق ناقل إلى آخر بعد الإنشاء ، vector :: insert هو أفضل رهان ، كما تمت الإجابة عليه عدة مرات ، على سبيل المثال:

vector first = {13};
const vector second = {42};

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

Sadly there's no way to construct a const vector, as above you must construct and then insert.


If what you're actually looking for is a container to hold the concatenation of these two vectors, there may be something better available to you, if:

  1. يحتوي متجه على الأوليات
  2. تكون الأوليات الأولية الخاصة بك بحجم 32 بت أو أصغر
  3. تريد حاوية const

إذا كان كل ما سبق صحيحًا ، فأقترح استخدام basic_string الذي يتطابق char_type مع حجم البادئة الموجودة في المتجه . يجب تضمين static_assert في شفرتك إلى التحقق من صحة هذه الأحجام تبقى ثابتة:

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

مع هذا عقد صحيح يمكنك القيام به:

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

For more information on the differences between string and vector you can look here: https://stackoverflow.com/a/35558008/2642059

For a live example of this code you can look here: http://ideone.com/7Iww3I

0
وأضاف

لنكون صادقين ، يمكنك بسرعة تجميع متصلين عن طريق نسخ عناصر من متجهين إلى آخر أو مجرد إلحاق واحد من اثنين من المتجهات !. ذلك يعتمد على هدفك.

Method 1: Assign new vector with its size is the sum of two original vectors' size.

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

Method 2: Append vector A by adding/inserting elements of vector 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());
0
وأضاف
ماذا تضيف إجابتك التي لم يتم تقديمها بالفعل في إجابات أخرى؟
وأضاف المؤلف Mat, مصدر
إذا لم يعد هناك حاجة إلى المتجه (النواقل) الأصلية بعد ، فقد يكون من الأفضل استخدام std :: move_iterator حتى يتم نقل العناصر بدلاً من نسخها. (راجع en.cppreference.com/w/cpp/iterator/move_iterator ) .
وأضاف المؤلف tmlen, مصدر
Mat: أحرف غامقة.
وأضاف المؤلف marcv81, مصدر

يُعد تحسين الأداء العام لسَلسَتة هو التحقق من حجم المتجهات. ودمج/إدراج أصغر مع واحد أكبر.

//vector v1,v2;
if(v1.size()>v2.size()){
    v1.insert(v1.end(),v2.begin(),v2.end());
}else{
    v1.insert(v2.end(),v1.begin(),v1.end());
}
0
وأضاف