মানচিত্রের মানগুলি এসটিএল-তে ভেক্টরে অনুলিপি করুন


86

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

এটি করার সবচেয়ে পরিষ্কার উপায় কী?


যদি কীগুলির প্রয়োজন না হয় তবে পুরো মানচিত্রেরও প্রয়োজন হবে না। এই ক্ষেত্রে মানচিত্রে ভ্যাক্টরে এই প্রশ্নের বর্ণিত হিসাবে মানগুলি স্থানান্তরিত করার বিষয়টি বিবেচনা করুন ।
Nykodym

উত্তর:


61

আপনি এখানে সহজেই কোনও ব্যাপ্তি ব্যবহার করতে পারবেন না কারণ আপনি মানচিত্র থেকে যে পুনরাবৃত্তিকে পেয়েছেন তা একটি স্টাড :: জোড়কে বোঝায়, যেখানে আপনি যে ভিট্টরে সন্নিবেশ করানোর জন্য যে পুনরাবৃত্তির ব্যবহার করবেন তা ভেক্টরে সঞ্চিত ধরণের একটি অবজেক্টকে বোঝায়, যা (যদি আপনি কীটি বাদ দিচ্ছেন) কোনও জুড়ি নয়।

আমি প্রকৃতপক্ষে এটি আরও পরিষ্কার হয়ে যায় বলে মনে করি না:

#include <map>
#include <vector>
#include <string>
using namespace std;

int main() {
    typedef map <string, int> MapType;
    MapType m;  
    vector <int> v;

    // populate map somehow

    for( MapType::iterator it = m.begin(); it != m.end(); ++it ) {
        v.push_back( it->second );
    }
}

যা আমি সম্ভবত টেমপ্লেট ফাংশন হিসাবে আবার লিখব যদি আমি এটি একাধিকবার ব্যবহার করতে যাই। কিছুটা এইরকম:

template <typename M, typename V> 
void MapToVec( const  M & m, V & v ) {
    for( typename M::const_iterator it = m.begin(); it != m.end(); ++it ) {
        v.push_back( it->second );
    }
}

83
পাইথন আমাকে সত্যই খারাপ করেছে :-(
গিলাদ নাওর

4
সুন্দর, টেম্পলেট। সম্ভবত এটি একটি ধারক পরিবর্তে একটি আউটপুট পুনরাবৃত্তি দিন!
xtofl

স্কুরমিডেলের সমাধানটি আরও সুন্দর: অ্যাপ -> পি.সেকেন্ড ফান্টিকার সাথে 'ট্রান্সফর্ম' ফাংশনটি ব্যবহার করুন।
xtofl

4
আমি ওসামের রেজারে দৃ firm় বিশ্বাসী - অস্তিত্বগুলির অভাবে পরিচয় করিয়ে দিই না। রূপান্তর সমাধানের ক্ষেত্রে, আমাদের একটি সহায়ক ফাংশন প্রয়োজন যা সুস্পষ্ট লুপ সমাধানে প্রয়োজন হয় না। সুতরাং আমরা নামহীন ফাংশন না পাওয়া পর্যন্ত আমি আমার সমাধানটি দিয়ে যাচ্ছি।

4
ওকামের রেজার ব্যাখ্যার থেকে সাবধান থাকুন। নতুন নন-কনস্টেবল ভেরিয়েবল "এটি" উপস্থাপন করা শেষ পর্যন্ত নিরাপদ সমাধান নাও হতে পারে। এসটিএল অ্যালগরিদমগুলি বেশ কিছু সময়ের জন্য দ্রুত এবং শক্তিশালী প্রমাণিত হয়েছে।
ভিনসেন্ট রবার্ট

62

আপনি সম্ভবত std::transformসেই উদ্দেশ্যে ব্যবহার করতে পারেন । আমি আরও বেশি পঠনযোগ্য যা তার উপর নির্ভর করে নীল সংস্করণটি পছন্দ করব।


Xtofl দ্বারা উদাহরণ (মন্তব্য দেখুন):

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

template< typename tPair >
struct second_t {
    typename tPair::second_type operator()( const tPair& p ) const { return p.second; }
};

template< typename tMap > 
second_t< typename tMap::value_type > second( const tMap& m ) { return second_t< typename tMap::value_type >(); }


int main() {
    std::map<int,bool> m;
    m[0]=true;
    m[1]=false;
    //...
    std::vector<bool> v;
    std::transform( m.begin(), m.end(), std::back_inserter( v ), second(m) );
    std::transform( m.begin(), m.end(), std::ostream_iterator<bool>( std::cout, ";" ), second(m) );
}

খুব জেনেরিক, আপনি যদি এটি দরকারী মনে করেন তবে তাকে ক্রেডিট দিতে ভুলবেন না।


যা আমি নীলের চেয়েও ভাল পছন্দ করি। কাজের ফাঁকা
xtofl

আমি শেষ প্যারামিটারের জন্য ল্যাম্বডা ব্যবহার করার পরামর্শ দেব।
ওয়ারেপসিলন

@ ওয়ারেপসিলন: সম্ভবত একটি ভাল ধারণা (যদি কেউ একটি আধুনিক সি ++ সংকলক নিয়ে থাকেন) তবে আমি সি ++ এর সাথে এতটা আত্মবিশ্বাসী নই, আমি এই মুহুর্তে সি সিড্ডার মতো আছি। যদি কেউ এটির উন্নতি করতে চান এবং ভাবেন যে তারা এটি করতে পারে তবে দয়া করে এগিয়ে যান :)
স্কুরমেডেল

30

পুরানো প্রশ্ন, নতুন উত্তর। সি ++ 11 এর সাথে আমাদের লুপের জন্য অভিনব নতুন রয়েছে:

for (const auto &s : schemas)
   names.push_back(s.first);

যেখানে স্কিমা একটি std::mapএবং নামগুলি একটি std::vector

এটি মানচিত্র (স্কিমাস) থেকে কীগুলি সহ অ্যারে (নামগুলি )কে পপুলেট করে; পরিবর্তন s.firstকরার জন্য s.secondমূল্যবোধের একটি অ্যারের জন্য।


4
এটি হওয়া উচিতconst auto &s
স্লাভা

4
@ স্লাভা এর জন্য ভিত্তি করে নতুন যে কোনও একটির জন্য স্পষ্ট করে দিতে: আমি যেভাবে এটি লিখেছি তা কাজ করে, তবে স্লাভা প্রস্তাবিত সংস্করণটি আরও দ্রুত এবং নিরাপদ কারণ একটি রেফারেন্স ব্যবহার করে পুনরাবৃত্তিকারী অবজেক্টটি অনুলিপি করা এড়ানো যায় এবং এটি একটি কনস্টকে নির্দিষ্ট করে যেহেতু এটি হবে পুনরুক্তি সংশোধন করা বিপজ্জনক। ধন্যবাদ
শেঠ

4
সবচেয়ে সংক্ষিপ্ত এবং পরিষ্কার সমাধান। এবং সম্ভবত দ্রুততম (গৃহীত সমাধানের চেয়ে দ্রুত এবং পরীক্ষাগুলি @ অ্যারাগর্নেক্সের সমাধানের চেয়েও দ্রুত)। যোগ করুন reserve()এবং আপনি অন্য কর্মক্ষমতা লাভ পাবেন। সি ++ 11 এর আবির্ভাবের সাথে এটি এখন গ্রহণযোগ্য সমাধান হওয়া উচিত!
অ্যাড্রিয়ান ডাব্লু

4
এটি নাম থাকতে হবে না। Push_back (s.second); প্রশ্নটি ভেক্টরের কীগুলি নয়, মানগুলি জিজ্ঞাসা করে?
ডেভিড

24

আপনি যদি বুস্ট লাইব্রেরিগুলি ব্যবহার করে থাকেন তবে আপনি জোড়ার :: বাইন্ডটি জোড়ার দ্বিতীয় মানটি অ্যাক্সেসের জন্য নিম্নলিখিতভাবে ব্যবহার করতে পারেন:

#include <string>
#include <map>
#include <vector>
#include <algorithm>
#include <boost/bind.hpp>

int main()
{
   typedef std::map<std::string, int> MapT;
   typedef std::vector<int> VecT;
   MapT map;
   VecT vec;

   map["one"] = 1;
   map["two"] = 2;
   map["three"] = 3;
   map["four"] = 4;
   map["five"] = 5;

   std::transform( map.begin(), map.end(),
                   std::back_inserter(vec),
                   boost::bind(&MapT::value_type::second,_1) );
}

এই সমাধানটি মেলিং তালিকার উত্সাহে মাইকেল গোল্ডশটেনের একটি পোস্টের ভিত্তিতে তৈরি ।


24
#include <algorithm> // std::transform
#include <iterator>  // std::back_inserter
std::transform( 
    your_map.begin(), 
    your_map.end(),
    std::back_inserter(your_values_vector),
    [](auto &kv){ return kv.second;} 
);

দুঃখিত যে আমি কোনও ব্যাখ্যা যোগ করি নি - আমি ভেবেছিলাম যে কোডটি এত সহজ যে কোনও ব্যাখ্যা প্রয়োজন হয় না। সুতরাং:

transform( beginInputRange, endInputRange, outputIterator, unaryOperation)

এই ফাংশনটি রেঞ্জ ( - ) unaryOperationথেকে প্রতিটি আইটেমে কল করে । অপারেশন এর মান সংরক্ষণ করা হয় ।inputIteratorbeginInputRangeendInputRangeoutputIterator

আমরা যদি পুরো মানচিত্রের মাধ্যমে পরিচালনা করতে চাই - আমরা আমাদের ইনপুট পরিসর হিসাবে map.begin () এবং map.end () ব্যবহার করি। আমরা ভেক্টর মধ্যে আমাদের মানচিত্র মান সঞ্চয় করতে চান - তাই আমরা আমাদের ভেক্টর উপর back_inserter ব্যবহার করতে হবে: back_inserter(your_values_vector)। ব্যাক_ইনসেটর হল একটি বিশেষ আউটপুটআইট্রেটর যা প্রদত্ত (প্যারামিটার হিসাবে) সংগ্রহের শেষে নতুন উপাদানগুলিকে ঠেলে দেয়। শেষ প্যারামিটারটি অযৌক্তিকরণ - এটি কেবল একটি প্যারামিটার নেয় - ইনপুটআইট্রেটারের মান। সুতরাং আমরা ল্যাম্বদা ব্যবহার করতে পারি: [](auto &kv) { [...] }যেখানে & কেভি হ'ল মানচিত্রের আইটেমের জোড়ার উল্লেখ। সুতরাং আমরা যদি মানচিত্রের আইটেমগুলির কেবলমাত্র মানগুলি ফিরিয়ে দিতে চাই তবে আমরা কেবল কেভি.সেকেন্ডটি ফিরিয়ে দিতে পারি:

[](auto &kv) { return kv.second; }

আমি মনে করি এটি কোনও সন্দেহের ব্যাখ্যা দেয়।


4
হাই, কোডটি আপনার কোডটি বুঝতে সহায়তা করে বলে কোডের সাথে কিছুটা ব্যাখ্যা যোগ করুন। কোডগুলি কেবলমাত্র উত্তরগুলি ভ্রমন করে।
ভরতভ রাও

4
হ্যাঁ! এই কোড স্নিপেট প্রশ্নটি সমাধান করতে পারে, একটি ব্যাখ্যা সহ সত্যিই আপনার পোস্টের মান উন্নত করতে সহায়তা করে। মনে রাখবেন যে আপনি ভবিষ্যতে পাঠকদের জন্য প্রশ্নের উত্তর দিচ্ছেন, এবং সেই লোকেরা আপনার কোড পরামর্শের কারণগুলি জানেন না।
জে ছোমেল

আমি মনে করি এটি কেবল সি ++ 14 থেকে শুরু করে, যেহেতু ল্যাম্বদার আগে তার আগে অটো সমর্থিত নয়। সুস্পষ্ট ফাংশন স্বাক্ষর এখনও কাজ করবে।
তুরনি

19

ল্যাম্বডাস ব্যবহার করে যে কেউ নিম্নলিখিতটি সম্পাদন করতে পারেন:

{
   std::map<std::string,int> m;
   std::vector<int> v;
   v.reserve(m.size());
   std::for_each(m.begin(),m.end(),
                 [&v](const std::map<std::string,int>::value_type& p) 
                 { v.push_back(p.second); });
}

4
আমার মনে হয় না আপনাকে v.re সংরক্ষণ করা দরকার (এম। সাইজ ()) কারণ আপনি নতুন উপাদানগুলিকে ধাক্কা দেওয়ার সাথে সাথে ভি বাড়বে।
ড্রাগন অস্টোজিć

11
@ ড্রাগনস্টোজিć। রিজার্ভ () কেবলমাত্র একটি পুনর্বিবেচনার কারণ। উপাদানের সংখ্যার উপর নির্ভর করে .push_back () একই আকারে পেতে একাধিক বরাদ্দ সম্পাদন করতে পারে।
এমএসকিফিশার

8

এখানে আমি কি করব।
এছাড়াও আমি সিলেক্ট 2 এর নির্মাণ সহজ করার জন্য একটি টেম্পলেট ফাংশন ব্যবহার করব।

#include <map>
#include <vector>
#include <algorithm>
#include <memory>
#include <string>

/*
 * A class to extract the second part of a pair
 */   
template<typename T>
struct select2nd
{
    typename T::second_type operator()(T const& value) const
    {return value.second;}
};

/*
 * A utility template function to make the use of select2nd easy.
 * Pass a map and it automatically creates a select2nd that utilizes the
 * value type. This works nicely as the template functions can deduce the
 * template parameters based on the function parameters. 
 */
template<typename T>
select2nd<typename T::value_type> make_select2nd(T const& m)
{
    return select2nd<typename T::value_type>();
}

int main()
{
    std::map<int,std::string>   m;
    std::vector<std::string>    v;

    /*
     * Please note: You must use std::back_inserter()
     *              As transform assumes the second range is as large as the first.
     *              Alternatively you could pre-populate the vector.
     *
     * Use make_select2nd() to make the function look nice.
     * Alternatively you could use:
     *    select2nd<std::map<int,std::string>::value_type>()
     */   
    std::transform(m.begin(),m.end(),
                   std::back_inserter(v),
                   make_select2nd(m)
                  );
}

4
ভাল একটা. এবং কেন Make_select2nd স্টলে নেই?
মাইকোলা গোলুয়েভ

সিলেক্ট 2 তম এসজিআই সংস্করণে (তাই বেসরকারী) এসটিএলে একটি এক্সটেনশন। ইউটিলিটি হিসাবে ফাংশন টেমপ্লেট যুক্ত করা এখন দ্বিতীয় প্রকৃতি (অনুপ্রেরণার জন্য Make_pair <> () দেখুন)।
মার্টিন ইয়র্ক

2

একটি উপায় ফান্টেক্টর ব্যবহার করা:

 template <class T1, class T2>
    class CopyMapToVec
    {
    public: 
        CopyMapToVec(std::vector<T2>& aVec): mVec(aVec){}

        bool operator () (const std::pair<T1,T2>& mapVal) const
        {
            mVec.push_back(mapVal.second);
            return true;
        }
    private:
        std::vector<T2>& mVec;
    };


int main()
{
    std::map<std::string, int> myMap;
    myMap["test1"] = 1;
    myMap["test2"] = 2;

    std::vector<int>  myVector;

    //reserve the memory for vector
    myVector.reserve(myMap.size());
    //create the functor
    CopyMapToVec<std::string, int> aConverter(myVector);

    //call the functor
    std::for_each(myMap.begin(), myMap.end(), aConverter);
}

আমি পরিবর্তনশীল aConverter নিয়ে বিরক্ত করব না। কেবলমাত্র_আরচে একটি অস্থায়ী তৈরি করুন। std :: for_each (myMap.begin (), myMap.end (), copyMapToVec <std :: স্ট্রিং, ইন্ট> (মাইভেক্টর));
মার্টিন ইয়র্ক

'ট্রান্সফর্ম' পছন্দ করুন, যেহেতু আপনি যা করছেন তা: বেশ সরল ফান্টর ব্যবহার করে মানচিত্রকে ভেক্টরে রূপান্তর করা।
xtofl

2

কেন না:

template<typename K, typename V>
std::vector<V> MapValuesAsVector(const std::map<K, V>& map)
{
   std::vector<V> vec;
   vec.reserve(map.size());
   std::for_each(std::begin(map), std::end(map),
        [&vec] (const std::map<K, V>::value_type& entry) 
        {
            vec.push_back(entry.second);
        });
    return vec;
}

ব্যবহার:

Auto vec = MapValuesAsVector (যে কোনও মানচিত্র);


আমি মনে করি আপনার গ্রাম শক্তি সমিতির দ্বিগুণ আকার হবে মানচিত্র
dyomas

ধন্যবাদ ডায়মাস, আমি পুনরায়
আকারের

2

আমি ভেবেছিলাম এটা হওয়া উচিত

std::transform( map.begin(), map.end(), 
                   std::back_inserter(vec), 
                   boost::bind(&MapT::value_type::first,_1) ); 

2

আমাদের এসটিএল অ্যালগরিদম থেকে ট্রান্সফর্ম ফাংশনটি ব্যবহার করা উচিত, ট্রান্সফর্ম ফাংশনের শেষ পরামিতি কোনও ফাংশন অবজেক্ট, ফাংশন পয়েন্টার বা ল্যাম্বডা ফাংশন হতে পারে যা মানচিত্রের আইটেমটিকে ভেক্টরের আইটেমে রূপান্তর করে। এই ক্ষেত্রে মানচিত্রে আইটেমগুলির মধ্যে টাইপ পেয়ার রয়েছে যা ভেক্টরের জন্য আইটেম রূপান্তর করতে হবে যা ইনট টাইপ রয়েছে। আমি ল্যাম্বদা ফাংশনটি ব্যবহার করি এটি এখানে আমার সমাধান:

#include <algorithm> // for std::transform
#include <iterator>  // for back_inserted

// Map of pair <int, string> need to convert to vector of string
std::map<int, std::string> mapExp = { {1, "first"}, {2, "second"}, {3, "third"}, {4,"fourth"} };

// vector of string to store the value type of map
std::vector<std::string> vValue;

// Convert function
std::transform(mapExp.begin(), mapExp.end(), std::back_inserter(vValue),
       [](const std::pair<int, string> &mapItem)
       {
         return mapItem.second;
       });

-3

অবাক বিস্মিত কেউই সবচেয়ে সুস্পষ্ট সমাধানের কথা উল্লেখ করেনি , স্ট্যান্ড :: ভেক্টর কনস্ট্রাক্টর ব্যবহার করুন use

template<typename K, typename V>
std::vector<std::pair<K,V>> mapToVector(const std::unordered_map<K,V> &map)
{
    return std::vector<std::pair<K,V>>(map.begin(), map.end());
}

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