জোড়ের দ্বিতীয় উপাদানটির উপর ভিত্তি করে আমি জোড়গুলির কোনও ভেক্টরকে কীভাবে সাজান?


133

আমার যদি জোড়গুলির ভেক্টর থাকে:

std::vector<std::pair<int, int> > vec;

জোড়ার দ্বিতীয় উপাদানটির উপর ভিত্তি করে ক্রম বর্ধমানে তালিকাটি সাজানোর কি সহজ উপায় আছে?

আমি জানি যে আমি একটি সামান্য ফাংশন অবজেক্ট লিখতে পারি যা কাজটি করবে তবে এসটিএলের বিদ্যমান অংশগুলি ব্যবহার std::lessকরার এবং সরাসরি কাজটি করার কোনও উপায় আছে কি?

সম্পাদনা: আমি বুঝতে পারি যে আমি বাছাই করতে তৃতীয় আর্গুমেন্টে পাস করার জন্য একটি পৃথক ফাংশন বা শ্রেণি লিখতে পারি। প্রশ্নটি হ'ল আমি এটি স্ট্যান্ডার্ড স্টাফের বাইরে তৈরি করতে পারি কিনা। আমি দেখতে সত্যিই এমন কিছু চাই:

std::sort(vec.begin(), vec.end(), std::something_magic<int, int, std::less>());

এখানে একটি উদাহরণ দেওয়া হল: <br> std :: জোড়া ভেক্টর সাজান
LeppyR64

1
সি ++ এ লামদাস নেই তাই আপনি যা চান ঠিক তেমন করতে পারবেন না, আপনাকে একটি পৃথক ফাংশন / ফান্টিকার তৈরি করতে হবে। এটি ওয়ান-লাইনার হতে পারে তাই এটি সত্যিই বড় বিষয় হওয়া উচিত নয়।
ইভান তেরান

1
সি ++ এ এখন লম্বাডাস আছে! উ!
ডেভিড পুল

উত্তর:


212

সম্পাদনা করুন : সি ++ 14 ব্যবহার করে, ল্যাম্বডাসকে ধন্যবাদ লেখার জন্য সেরা সমাধানটি খুব সহজ যা এখন টাইপের পরামিতি থাকতে পারে autoএটি আমার বর্তমান প্রিয় সমাধান

std::sort(v.begin(), v.end(), [](auto &left, auto &right) {
    return left.second < right.second;
});

কেবলমাত্র একটি কাস্টম তুলক ব্যবহার করুন (এটি একটি 3rdচ্ছিক তৃতীয় যুক্তি std::sort)

struct sort_pred {
    bool operator()(const std::pair<int,int> &left, const std::pair<int,int> &right) {
        return left.second < right.second;
    }
};

std::sort(v.begin(), v.end(), sort_pred());

আপনি যদি C ++ 11 সংকলক ব্যবহার করেন তবে ল্যাম্বডাস ব্যবহার করে আপনি এটি লিখতে পারেন:

std::sort(v.begin(), v.end(), [](const std::pair<int,int> &left, const std::pair<int,int> &right) {
    return left.second < right.second;
});

সম্পাদনা : আপনার প্রশ্নের আপনার সম্পাদনাগুলির জবাবে, এখানে কিছু চিন্তাভাবনা রয়েছে ... আপনি যদি সত্যিই সৃজনশীল হতে চান এবং এই ধারণাটি অনেক ব্যবহার করতে সক্ষম হন তবে কেবল একটি টেমপ্লেট তৈরি করুন:

template <class T1, class T2, class Pred = std::less<T2> >
struct sort_pair_second {
    bool operator()(const std::pair<T1,T2>&left, const std::pair<T1,T2>&right) {
        Pred p;
        return p(left.second, right.second);
    }
};

তাহলে আপনি এটিও করতে পারেন:

std::sort(v.begin(), v.end(), sort_pair_second<int, int>());

অথবা এমনকি

std::sort(v.begin(), v.end(), sort_pair_second<int, int, std::greater<int> >());

সত্য কথা বলা হলেও এগুলি কিছুটা ওভারকিল, কেবল 3 লাইন ফাংশনটি লিখুন এবং এটি দিয়ে সম্পন্ন করুন :- পি


মনে রাখবেন যে এই থেকে ভিন্ন operator<মধ্যে pair<T1,T2>। ডিফল্ট তুলনাকারী প্রথম এবং দ্বিতীয় উপাদান উভয়ই ব্যবহার করে (প্রথম ক্ষেত্রে সমান হলে)। এখানে কেবল দ্বিতীয়টি ব্যবহৃত হচ্ছে।
গুগল

@ গুগল: ওপি যা চেয়েছিল ঠিক তা-ও ... তিনি বলেছেন: "is there and easy way to sort the list in increasing order based on the second element of the pair?"
ইভান তেরান

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

71

আপনি এর মতো বুস্ট ব্যবহার করতে পারেন:

std::sort(a.begin(), a.end(), 
          boost::bind(&std::pair<int, int>::second, _1) <
          boost::bind(&std::pair<int, int>::second, _2));

এটি সমানভাবে সংক্ষিপ্ত এবং সংক্ষিপ্ত করার জন্য আমি কোনও স্ট্যান্ডার্ড উপায় জানি না, তবে আপনি boost::bindএটি হ্যাডারের সমন্বয়ে তৈরি করতে পারেন ।


1
বুস্ট ব্যবহারের জন্য +1। বিটিডব্লিউ, একটি আধুনিক সংকলক সহ আপনি সম্ভবত ইতিমধ্যে স্টাডি :: টিআর 1 এর সাথে বুস্ট প্রতিস্থাপন করতে পারেন কারণ এটি শিগগিরই স্ট্যান্ডার্ডে আসবে।
আন্দ্রেয়াস ম্যাগনুসন

দুর্ভাগ্যক্রমে, আমি জিসিসি ট্রাঙ্কের সি ++ 1x স্ট্যান্ড :: বাইন্ডের সাথে একই চেষ্টা করেছি এবং এটি ব্যর্থ হয়েছে কারণ এটির জন্য <বাইন্ডের জন্য বিকল্প নেই। dunno যাই হোক না কেন c ++ 1x এ সম্পর্কে বলে। সম্ভবত এটি আপনাকে সেই জন্য ল্যাম্বডা ব্যবহার করতে বলে :)
জোহানেস স্কাউব - লিটব

1
আমি মনে করি বুস্ট মানক নয়, তবে এটি যথেষ্ট কাছে। :-)
ডেভিড নরম্যান

এই উত্তরটি করার জন্য একটি ফলোআপ প্রশ্ন এখানে পোস্ট: stackoverflow.com/q/4184917/220636
nabulke

34

এটি খুব সহজ আপনি অ্যালগরিদম থেকে বাছাই ফাংশন ব্যবহার করুন এবং আপনার নিজস্ব তুলনা ফাংশন যোগ করুন

vector< pair<int,int > > v;
sort(v.begin(),v.end(),myComparison);

এখন আপনাকে দ্বিতীয় নির্বাচনের উপর ভিত্তি করে তুলনা করতে হবে সুতরাং আপনাকে "মাই কম্পোরিজেনশন" হিসাবে ঘোষণা করুন

bool myComparison(const pair<int,int> &a,const pair<int,int> &b)
{
       return a.second<b.second;
}

5
সহজ এবং যথাযথ". বুস্ট বা নির্দিষ্ট সি ++ সংস্করণ দরকার নেই। +1
থোমিও

1
এটি সেরা সমাধান হিসাবে চিহ্নিত করা উচিত। এটি বাস্তবায়নের জন্য সি ++ 14 দরকার নেই।
কার্তিক চৌহান

আপনি কি আমাকে ব্যাখ্যা করতে পারেন যে এই তুলনাটি কীভাবে কাজ করে? আমরা কি এক সাথে দুটি সময়ে মাইকম্পারেশনে পাস করছি তবে এটি কীভাবে বাছাই করতে সক্ষম? এছাড়াও, a.second <বি। সেকেন্ড কী ভূমিকা পালন করে?
যুগ s'q

30

C ++ 0x এর সাহায্যে আমরা ল্যাম্বদা ফাংশন ব্যবহার করতে পারি:

using namespace std;
vector<pair<int, int>> v;
        .
        .
sort(v.begin(), v.end(),
     [](const pair<int, int>& lhs, const pair<int, int>& rhs) {
             return lhs.second < rhs.second; } );

এই উদাহরণে প্রত্যাবর্তনের boolধরণটি নিখুঁতভাবে বিয়োগ করা হয়।

ল্যাম্বদা রিটার্ন টাইপ

যখন ল্যাম্বডা-ফাংশনে একটি একক বিবৃতি থাকে এবং এটি একটি রিটার্ন-বিবৃতি হয়, সংকলকটি রিটার্নের ধরণটি কেটে নিতে পারে। সি ++ 11, §5.1.2 / 4 থেকে:

...

  • যদি যৌগিক-বিবৃতিটি ফর্মের হয় { return expression ; }তবে লভ্যু-টু-রালু রূপান্তর (৪.১), অ্যারে-টু-পয়েন্টার রূপান্তর (৪.২), এবং ফাংশন-টু-পয়েন্টার রূপান্তর (৪.৩) এর পরে প্রত্যাবর্তনের মত প্রকাশের ধরণের হয়;
  • অন্যথায় void,।

সুস্পষ্টভাবে রিটার্ন টাইপ নির্দিষ্ট করতে ফর্মটি ব্যবহার করুন []() -> Type { }যেমন:

sort(v.begin(), v.end(),
     [](const pair<int, int>& lhs, const pair<int, int>& rhs) -> bool {
             if (lhs.second == 0)
                 return true;
             return lhs.second < rhs.second; } );

1
কেন if (lhs.second == 0)?
সোয়াইন

কোন বিশেষ অর্থ; lhs.second < rhs.secondফেরত দিতে পারেন trueবা falseএবং কম্পাইলার পরিষ্কারভাবে অনুমান করতে পারেন bool। কেবল []() -> Type { }মামলাটি প্রদর্শন করতে চেয়েছিলেন ।
আন্দ্রেয়াস স্পিন্ডার

কমপক্ষে ঝাঁকুনির সাথে, এই অন্তর্নিহিত ছাড়টি সঠিকভাবে কাজ করতে পারে না, আমাকে সঠিকভাবে কাজ করতে ল্যাম্বদা রিটার্ন টাইপ হিসাবে -> বুল যোগ করতে হয়েছিল।
MoDJ

5

পুনরায় ব্যবহারযোগ্য কিছু জন্য:

template<template <typename> class P = std::less >
struct compare_pair_second {
    template<class T1, class T2> bool operator()(const std::pair<T1, T2>& left, const std::pair<T1, T2>& right) {
        return P<T2>()(left.second, right.second);
    }
};

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

std::sort(foo.begin(), foo.end(), compare_pair_second<>());

অথবা

std::sort(foo.begin(), foo.end(), compare_pair_second<std::less>());


-1

জোড়াগুলির উপাদানগুলিকে অদলবদল করার চেষ্টা করুন যাতে আপনি std::sort()স্বাভাবিক হিসাবে ব্যবহার করতে পারেন ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.