আমি কীভাবে দু'জনকে সম্মতি জানাতে পারি std::vector
?
a + b
বা হিসাবে প্রয়োগ করা হয় না a.concat(b)
? হতে পারে ডিফল্ট বাস্তবায়ন suboptimal হবে, কিন্তু প্রতিটি অ্যারে সংক্ষিপ্ত বিবরণ মাইক্রো অনুকূলিতকরণ করা প্রয়োজন হয় না
আমি কীভাবে দু'জনকে সম্মতি জানাতে পারি std::vector
?
a + b
বা হিসাবে প্রয়োগ করা হয় না a.concat(b)
? হতে পারে ডিফল্ট বাস্তবায়ন suboptimal হবে, কিন্তু প্রতিটি অ্যারে সংক্ষিপ্ত বিবরণ মাইক্রো অনুকূলিতকরণ করা প্রয়োজন হয় না
উত্তর:
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
reserve
করে থাকেন তবে গন্তব্য ভেক্টরটিকে প্রথমে কল করা কি সহায়ক ?
vector1.capacity() >= 2 * vector1.size()
। আপনি না ডাকলে কোনটি এপিক্যাল std::vector::reserve()
। অন্যথায় ভেক্টর পুনরায় সরে যাবে, 2 এবং 3 পরামিতি হিসাবে পাস করা পুনরাবৃত্তিগুলি অকার্যকর করবে
.concat
বা +=
কিছু
আপনি যদি সি ++ 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;
}
এটি অন্তর্নিহিত উদাহরণগুলির জন্য আরও কার্যকর হবে না, যেহেতু এগুলি সরিয়ে নেওয়া তাদের অনুলিপি করার চেয়ে বেশি কার্যকর নয়, তবে অনুকূলিত পদক্ষেপের সাথে ডেটা কাঠামোর জন্য এটি অপ্রয়োজনীয় অবস্থার অনুলিপি এড়াতে পারে:
#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;
}
সরানোর পরে, এসআরসি-র উপাদানটি একটি অপরিজ্ঞাত তবে নিরাপদ-থেকে-ধ্বংসাত্মক অবস্থায় ফেলে রাখা হয়েছে এবং এর পূর্বের উপাদানগুলি সরাসরি শেষের দিকে লক্ষ্যটির নতুন উপাদানে স্থানান্তরিত হয়েছিল।
std::move(src.begin(), src.end(), back_inserter(dest))
?
আমি সন্নিবেশ ফাংশনটি ব্যবহার করব , এরকম কিছু:
vector<int> a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
অথবা আপনি ব্যবহার করতে পারেন:
std::copy(source.begin(), source.end(), std::back_inserter(destination));
এই প্যাটার্নটি কার্যকর যদি দুটি ভেক্টর একই ধরণের জিনিস না রাখে, কারণ আপনি স্ট্যান্ড :: ব্যাক_ইনসেটর পরিবর্তে কিছু ব্যবহার করতে পারেন এক প্রকার থেকে অন্য রূপে রূপান্তর করতে।
reserve
প্রথমে কল করা কিছুতেই থামছে না । std::copy
আপনি ব্যতীত অন্য কিছু ব্যবহার করতে চাইলে কারণটি কখনও কখনও দরকারী back_inserter
।
সি ++ 11 দিয়ে আমি ভেক্টর বি কে যুক্ত করতে পছন্দ করব:
std::move(b.begin(), b.end(), std::back_inserter(a));
কখন a
এবং b
ওভারল্যাপ b
করা হবে না এবং আর ব্যবহার করা হবে না।
এই std::move
থেকে <algorithm>
, না স্বাভাবিক std::move
থেকে <utility>
।
insert
পথে ফিরে আসা উচিত যা নিরাপদ।
insert()
সাথে আলাদা move_iterator
? যদি তাই হয়, কিভাবে?
std::move
আমরা এখানে কী বলছি সে সম্পর্কে আমি একটি নোট যুক্ত করেছি , কারণ বেশিরভাগ লোকেরা এই ওভারলোড জানেন না know আশা করি এটির উন্নতি হবে।
std::vector<int> first;
std::vector<int> second;
first.insert(first.end(), second.begin(), second.end());
আমি ইতিমধ্যে উল্লিখিত একটি পছন্দ:
a.insert(a.end(), b.begin(), b.end());
তবে আপনি যদি সি ++ 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());
}
std::
হবে যখন প্রকারটি a
আসে std
, যা জেনেরিক দিকটিকে পরাস্ত করে।
আপনার ভেক্টর :: সন্নিবেশ করা উচিত
v1.insert(v1.end(), v2.begin(), v2.end());
একজন সাধারণ কর্মক্ষমতা বুস্ট CONCATENATE জন্য ভেক্টর আকার করা উচিত নয়। এবং বৃহত্তরটির সাথে ছোটটি একত্রীকরণ / sertোকান।
//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());
}
v1.insert(v2.end()...
একটি পুনরাবৃত্তকারী ব্যবহার v2
করছে v1
।
আপনি যদি সংক্ষিপ্তভাবে ভেক্টরগুলিকে একত্রিত করতে সক্ষম হতে চান তবে আপনি +=
অপারেটরটিকে ওভারলোড করতে পারেন ।
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;
আপনি যদি দৃ strong় ব্যতিক্রম গ্যারান্টিতে আগ্রহী হন (যখন অনুলিপি নির্মাণকারী একটি ব্যতিক্রম নিক্ষেপ করতে পারেন):
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;
}
}
দৃ ve append_move
় গ্যারান্টি সহ সাধারণভাবে কার্যকর করা যায় না যদি ভেক্টর এলিমেন্টের মুভ কনস্ট্রাক্টর নিক্ষেপ করতে পারেন (যা সম্ভাব্য নয় তবে এখনও)।
v1.erase(...
খুব নিক্ষেপ করা সম্ভব হয় না?
insert
ইতিমধ্যে এটি পরিচালনা করে এছাড়াও, এই কলটি erase
a এর সমতুল্য resize
।
আপনার হেডার ফাইলটিতে এটি যুক্ত করুন:
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);
আর এতে [1,2,62] টি থাকবে
সি ++ 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);
}
এটি কীভাবে append
পরিবর্তিত হয় তা নোট করুন vector
।
আপনি + অপারেটরের জন্য আপনার নিজস্ব টেম্পলেট প্রস্তুত করতে পারেন:
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
T operator+(const T & a, const T & b)
করা বিপজ্জনক, এটি ব্যবহার করা ভাল vector<T> operator+(const vector<T> & a, const vector<T> & b)
।
সি ++ 17std::merge
থেকে একটি অ্যালগরিদম রয়েছে , যা ব্যবহার করা খুব সহজ,
নীচে উদাহরণ দেওয়া হল:
#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;
}
std::vector::insert
তবে এটি অন্যরকম কিছু করে: দুটি রেঞ্জকে নতুন পরিসরে একত্রিত করে বনাম অন্যটির শেষে একটি ভেক্টর সন্নিবেশ করানো। উত্তরে উল্লেখযোগ্য?
যদি আপনার লক্ষ্যটি কেবলমাত্র পঠনযোগ্য উদ্দেশ্যে মানগুলির সীমার মধ্যে পুনরাবৃত্তি হয় তবে একটি বিকল্প হ'ল উভয় ভেক্টরকে (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' বাস্তবায়ন সেইসাথে অনুকূল & কনস সহ, আরো বিস্তারিত জানার জন্য।
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));
আমি এই ফাংশনটি প্রয়োগ করেছি যা কোনও সংখ্যক ধারককে সম্মতি দেয়, মূল্য-রেফারেন্সগুলি থেকে সরানো হয় এবং অন্যথায় অনুলিপি করে
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;
}
আপনি যা সন্ধান করছেন তা যদি সৃষ্টির পরে অন্য কোনও ভেক্টরকে যুক্ত করার উপায় হয় 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>
যদি থাকে তবে আপনার কাছে আরও ভাল কিছু উপলভ্য হতে পারে, যদি:
vector
মধ্যে আদিম রয়েছে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
এই সমাধানটি কিছুটা জটিল হতে পারে তবে 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
এটি কিছু অপারেশন করে কেবল পুনরাবৃত্তি করা rate এই ক্ষেত্রে, হাস্যকর সহজ 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;
}
বড় ভেক্টরগুলির জন্য এটি কোনও সুবিধা হতে পারে, কারণ কোনও অনুলিপি নেই। এটি একাধিক পাত্রে সহজেই জেনারালাইজগুলি অনুলিপি করার জন্য ব্যবহার করা যেতে পারে।
কিছু কারণে এর মতো কিছুই নেই boost::join(a,b,c)
, যা যুক্তিসঙ্গত হতে পারে।
পলিমারফিক টাইপের ব্যবহারের জন্য টেমপ্লেট ব্যবহার করে আপনি এটি প্রাক-বাস্তবায়িত এসটিএল অ্যালগরিদম দিয়ে করতে পারেন।
#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()
পদ্ধতি) ব্যবহার করতে না চান তবে আপনি সাফ করতে পারেন ।
একটিতে লুপ std::vector-s
দিয়ে দু'জনকে সংঘবদ্ধ করুন ।for
std::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(auto i = 0; i < v1.size()-1;i++)//for loop 1
{
suma.push_back(v1[i]);
}
for(auto i = 0; i< v2.size()-1;i++)/for loop 2
{
suma.push_back(v2[i]);
}
for(auto i = 0; i < suma.size(); i++)//for loop 3-output
{
std::cout<<suma[i];
}
এই কোড লিখুন main()
।
for
লুপগুলি ভুল। কোনও ভেক্টরের বৈধ সূচকগুলি 0 থেকে শুরু করে size()-1
। আপনি লুপ সমাপ্তির শর্তগুলি অবশ্যই i < v1.size()
ব্যবহার করবেন <
না <=
। ভুল শর্তটি ব্যবহার করে ধারকটির বাইরে স্মৃতিতে প্রবেশ করে।
auto
ম্যানুয়াল ইনডেক্সের পরিবর্তে কমপক্ষে পুনরায় ব্যবহার করা উচিত । আপনি কোন সূচকটি একত্রিত করছেন তা কেবল পরিকল্পিতভাবে করা হয় সে বিষয়ে আপনার চিন্তা নেই।
size()-1
দুটি লুপ শর্তে ব্যবহার করছেন ? এটি সর্বশেষ ভেক্টর উপাদানগুলি এড়িয়ে চলে। তৃতীয় লুপটি এখন একমাত্র সঠিক।
সত্যি কথা বলতে, আপনি দ্রুত দুটি ভেক্টরকে দুটি ভেক্টর থেকে অন্য একটিতে অনুলিপি করে অন্য দুটি ভেক্টরগুলির মধ্যে কেবল একটি সংযোজন করতে পারেন! এটি আপনার লক্ষ্য উপর নির্ভর করে।
পদ্ধতি 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: ভেক্টর বি এর উপাদান যুক্ত / সন্নিবেশ করে ভেক্টর এ সংযুক্ত করুন
// 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());
std::move_iterator
so যাতে উপাদানগুলি অনুলিপি করার পরিবর্তে সরানো হয়। ( en.cppreferences.com/w/cpp/iterator/move_iterator দেখুন )।
setcapacity
? কী function:
?
resize
পদ্ধতি সম্পর্কে কথা বলছেন ।