সি ++, অনুলিপি ভেক্টরে সেট করুন


146

আমার এখানে অনুলিপি std::setকরা দরকার std::vector:

std::set <double> input;
input.insert(5);
input.insert(6);

std::vector <double> output;
std::copy(input.begin(), input.end(), output.begin()); //Error: Vector iterator not dereferencable

সমস্যা কোথায়?


5
এছাড়াও রয়েছে assign():output.assign(input.begin(), input.end());
জিন বুশুয়েভ

আপনার ভেক্টর খালি আছে। প্রতিকারের জন্য প্রচুর উপায় রয়েছে যা যদিও মানুষ নীচের দিকে নির্দেশ করছে।
এজেজি 85

@ জিন: নির্ধারিত () সময়ের পূর্বে প্রয়োজনীয় পরিমাণ স্টোরেজ () সংরক্ষণ করতে চায়। এটি ইনপুট পুনরাবৃত্তিকারীদের কতটুকু প্রয়োজন তা নির্ধারণ করতে ব্যবহার করবে, যদি না পুনরুক্তিকারীরা কঠোরভাবে ইনপুটআইটিরেটার না হয় তবে সেক্ষেত্রে এটি সংরক্ষণ করা এড়িয়ে যাবে এবং প্রতিটি পুশ_ব্যাক () এ পুনঃনির্ধারণের ফলস্বরূপ। বর্ণালীটির বিপরীত প্রান্তে, দ্বিদ্বিধায়িকাশক্তিরা এটিকে কেবল শেষ বিয়োগ করতে শুরু করবে - শুরু করতে। std :: সেট এর পুনরাবৃত্তিগুলি উভয়ই নয় (তারা ফরওয়ার্ডইট্রেটার), এবং এটি দুর্ভাগ্যজনক: এই ক্ষেত্রে, নির্ধারণ () কেবলমাত্র তার আকার নির্ধারণের জন্য পুরো সেটটি হাঁটবে - বড় সেটগুলিতে খারাপ সম্পাদনা।
সের্গে শেভচেঙ্কো

উত্তর:


213

আপনার একটি ব্যবহার করতে হবে back_inserter:

std::copy(input.begin(), input.end(), std::back_inserter(output));

std::copyআপনি যে পাত্রে সন্নিবেশ করছেন তাতে উপাদান যুক্ত করে না: এটি পারে না; এটির ধারকটিতে কেবল একটি পুনরাবৃত্তি রয়েছে। এর কারণ হিসাবে, আপনি যদি কোনও আউটপুট পুনরাবৃত্তিকে সরাসরি এতে পাস করেন তবে আপনাকে std::copyঅবশ্যই নিশ্চিত করতে হবে যে এটি ইনপুট সীমাটি ধরে রাখতে কমপক্ষে যথেষ্ট বড় একটি ব্যাপ্তিকে নির্দেশ করে।

std::back_inserterএকটি আউটপুট পুনরাবৃত্তি তৈরি করে যা push_backপ্রতিটি উপাদানটির জন্য একটি ধারককে কল করে, তাই প্রতিটি উপাদান পাত্রে sertedোকানো হয়। বিকল্পভাবে, আপনি std::vectorসীমাটি অনুলিপি করার জন্য পর্যাপ্ত পরিমাণে উপাদান তৈরি করতে পারতেন :

std::vector<double> output(input.size());
std::copy(input.begin(), input.end(), output.begin());

অথবা, আপনি std::vectorব্যাপ্তি নির্মাণকারী ব্যবহার করতে পারেন :

std::vector<double> output(input.begin(), input.end()); 

3
হাই জেমস, আপনার এসটিডি :: কপি লাইন (আপনার উত্তর প্রথম কোড ব্লক) পরিবর্তে, আমি শুধু যেত না output.insert(output.end(), input.begin(), input.end());পরিবর্তে?
user2015453

বা কেবল সিবেগিন এবং সেন্ট সংস্করণটি ব্যবহার করুন: আপনার output.insert(output.cend(), input.cbegin(), input.cend());কী মনে হয়? ধন্যবাদ।
ব্যবহারকারী2015453

2
আমার কি আউটপুট.রিজার করা উচিত (ইনপুট.সাইজ ()); আমার দ্বারা বা আমি আশা করতে পারি যে কোনও সংকলক এটি আমার জন্য করে?
জিমফিকি ২

@ জিমিফিকি, আশা করি আমি ভয় পাচ্ছি না।
অ্যালেক্সিস উইলক

আপনার প্রথম ভেক্টর সূচনাটি ভুল। আপনি input,size()খালি এন্ট্রিগুলির একটি অ্যারে তৈরি করেন এবং তারপরে সংযোজনগুলি যুক্ত করুন। আমি মনে করি আপনি ব্যবহার করতে চাইছেন std::vector<double> output; output.reserve(input.size()); std::copy(...);
অ্যালেক্সিস উইলক

121

পুনরুক্তিকারীগুলির জন্য কেবল ভেক্টরের জন্য কনস্ট্রাক্টরটি ব্যবহার করুন:

std::set<T> s;

//...

std::vector v( s.begin(), s.end() );

ধরে নিই আপনি কেবল v এর s সামগ্রীগুলি চান এবং এতে ডেটা অনুলিপি করার আগে v তে কিছুই নেই।


42

এখানে অন্য বিকল্প ব্যবহার করে vector::assign:

theVector.assign(theSet.begin(), theSet.end());

24

আপনার সেটের বিষয়বস্তু ধরে রাখতে আপনি আপনার ভেক্টর অবজেক্টে পর্যাপ্ত জায়গা সংরক্ষণ করেননি।

std::vector<double> output(input.size());
std::copy(input.begin(), input.end(), output.begin());

1
এটি -1 প্রাপ্য নয়। বিশেষত, এটি ভেক্টরকে কেবলমাত্র একটি বরাদ্দ করতে দেয় (যেহেতু এটি ও (1) এ সেট পুনরাবৃত্তির দূরত্ব নির্ধারণ করতে পারে না), এবং যদি এটি নির্মাণের সময় ভেক্টরের জন্য প্রতিটি উপাদান শূন্যের জন্য সংজ্ঞায়িত না করা হত, এটি হতে পারে অনুলিপিটি একটি মেমকিতে সিদ্ধ হওয়ার অনুমতি দেওয়া উপযুক্ত। আধুনিকীকরণটি যদি ভেক্টরের কর্টরের লুপটি সরিয়ে ফেলা যায় তবে কার্যকর হতে পারে। অবশ্যই, প্রাক্তনটিও রিজার্ভ দিয়ে অর্জন করা যেতে পারে।
ফ্রেড নুরক

আমি জানি না। আমার যে আপনাকে সাহায্য করা যাক।
উইলহেমটেল

আমি আপনাকে একটি -1 দিয়েছিলাম তবে এটি আমার পক্ষে একটি থিঙ্কো ছিল। একটি ছোট সম্পাদনা করুন যাতে আমি আমার ভোটটি পূর্বাবস্থায় ফিরিয়ে আনতে পারি এবং আমি আপনাকে একটি +1 দেব: ব্যর্থ-প্রথম সম্পত্তি হিসাবে এটি আসলে খুব পরিষ্কার সমাধান।
ফ্রেড ফু

আমি কেবলমাত্র বুঝতে পেরেছি যে আমি যদি উত্তরটি নিজেই সম্পাদনা করি তবে আমি একটি উচ্চশক্তি করতে পারি। এটি কি, আপনাকে ব্যর্থ-প্রথম মেমরি বরাদ্দের জন্য একটি +1 দিয়েছে। দুঃখিত!
ফ্রেড ফু

3

আমি মনে করি সবচেয়ে কার্যকরী উপায় হ'ল উপাদানগুলি পূর্বরূপণ এবং তারপরে স্থানান্তর করা:

template <typename T>
std::vector<T> VectorFromSet(const std::set<T>& from)
{
    std::vector<T> to;
    to.reserve(from.size());

    for (auto const& value : from)
        to.emplace_back(value);

    return to;
}

প্রথমে ডিফল্ট কনস্ট্রাক্টরকে কল করার বিপরীতে আমরা কেবলমাত্র প্রতিটি উপাদানটির জন্য অনুলিপি কন্সট্রাক্টরকে অনুরোধ করব এবং তারপরে উপরের তালিকাভুক্ত অন্যান্য সমাধানগুলির জন্য অনুলিপি অ্যাসাইনমেন্ট অপারেটরকে অনুরোধ করব। নীচে আরও স্পষ্টতা।

  1. back_inserter ব্যবহার করা যেতে পারে তবে এটি ভেক্টর ( https://en.cppreferences.com/w/cpp/iterator/back_insert_iterator ) এর উপর পুশ_ব্যাক () আহ্বান করবে । এমপ্লেস_ব্যাক () আরও কার্যকর কারণ এটি পুশ_ব্যাক () ব্যবহার করার সময় অস্থায়ী তৈরি করা এড়ানো যায় । তুচ্ছভাবে নির্মিত ধরণের ক্ষেত্রে এটি সমস্যা নয় তবে তুচ্ছ-স্বল্পভাবে নির্মিত ধরণের (যেমন স্ট্যান্ড :: স্ট্রিং) এর কার্যকারিতা জড়িত।

  2. আকারের আর্গুমেন্টের সাথে আমাদের কোনও ভেক্টর তৈরি করা এড়াতে হবে যা সমস্ত উপাদানকে ডিফল্টরূপে তৈরি করে (কিছুই নয়) causes উদাহরণস্বরূপ, std :: copy () ব্যবহার করে সমাধানের মতো করুন ।

  3. এবং, অবশেষে, ভেক্টর :: অ্যাসাইনমেন্ট () পদ্ধতি বা কনট্রাক্টর পুনরুক্তি রেঞ্জ গ্রহণ করা ভাল বিকল্প নয় কারণ তারা সেট পুনরাবৃত্তিতে স্ট্যান্ড :: দূরত্ব () (উপাদানগুলির সংখ্যা জানতে) প্রার্থনা করবে । এটি সমস্ত সেট উপাদানগুলির মাধ্যমে অবাঞ্ছিত অতিরিক্ত পুনরাবৃত্তি ঘটায় কারণ সেটটি বাইনারি অনুসন্ধান গাছের ডেটা কাঠামো এবং এটি এলোমেলো অ্যাক্সেস পুনরাবৃত্তিকে কার্যকর করে না।

আশা করি এইটি কাজ করবে.


দয়া করে কোনও কর্তৃপক্ষের কাছে একটি রেফারেন্স যুক্ত করুন কেন এটি দ্রুত এবং কেন back_inserterব্যবহারের প্রয়োজন হয় না এর মতো কিছু
তারিক ওয়েলিং

উত্তরে আরও স্পষ্টতা যুক্ত করা হয়েছে।
dshvets1

1

std::copyখালি পাত্রে sertোকাতে ব্যবহার করা যাবে না। এটি করার জন্য, আপনাকে এর মতো একটি ইনসার্ট_লিটার ব্যবহার করতে হবে:

std::set<double> input;
input.insert(5);
input.insert(6);

std::vector<double> output;
std::copy(input.begin(), input.end(), inserter(output, output.begin())); 

3
এটি প্রথমবার ভেক্টর পুনরায় স্থান পরিবর্তন করতে ব্যর্থ: আউটপুট.বেগিন () থেকে পুনরাবৃত্তি অবৈধ হয়ে যায়।
ফ্রেড নুরক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.