কিভাবে একটি এসটিডি :: ম্যাপ থেকে সমস্ত কী (বা মান) উদ্ধার করবেন এবং সেগুলিকে কোনও ভেক্টরে রাখবেন?


246

এটি আমি বেরিয়ে আসা সম্ভাব্য উপায়গুলির মধ্যে একটি:

struct RetrieveKey
{
    template <typename T>
    typename T::first_type operator()(T keyValuePair) const
    {
        return keyValuePair.first;
    }
};

map<int, int> m;
vector<int> keys;

// Retrieve all keys
transform(m.begin(), m.end(), back_inserter(keys), RetrieveKey());

// Dump all keys
copy(keys.begin(), keys.end(), ostream_iterator<int>(cout, "\n"));

অবশ্যই, আমরা অন্য functor সংজ্ঞা দ্বারা মানচিত্র থেকে সব মান উদ্ধার করতে পারেন RetrieveValues

সহজেই এটি অর্জনের অন্য কোনও উপায় আছে কি? (আমি সবসময়ই ভাবছি যে কেন std :: মানচিত্রে এটি করার জন্য কোনও সদস্য ফাংশন অন্তর্ভুক্ত নয়))


10
আপনার সমাধানটি সেরা ...
লাইনলো

4
আমি মনে করি কেবল এটিই যুক্ত হবে keys.reserve(m.size());
গালিক

উত্তর:


176

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

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

map<int, int> m;
vector<int> v;
for(map<int,int>::iterator it = m.begin(); it != m.end(); ++it) {
  v.push_back(it->first);
  cout << it->first << "\n";
}

বা এমনকি সহজ, আপনি যদি বুস্ট ব্যবহার করছেন:

map<int,int> m;
pair<int,int> me; // what a map<int, int> is made of
vector<int> v;
BOOST_FOREACH(me, m) {
  v.push_back(me.first);
  cout << me.first << "\n";
}

ব্যক্তিগতভাবে, আমি BOOST_FOREach সংস্করণটি পছন্দ করি কারণ এখানে টাইপিং কম রয়েছে এবং এটি কী করছে তা এটি খুব স্পষ্ট।


1
আমার গুগল অনুসন্ধানের পরে আমি এখানে ফিরে এসেছি figures আপনার উত্তরটি আমি পছন্দ করি :)
এমপিএন

4
@ জের - আপনি কি আসলে কাজ করেছেন BOOST_FOREACH? আপনি এখানে যে কোডটি প্রস্তাব করেছেন তা সম্পূর্ণ ভুল
ম্যানুয়েল

2
@ জেমি - এটি অন্য এক উপায়, তবে বুস্ট ডকসগুলি BOOST_FOREach এর আগে ভেরিয়েবল এবং তার প্রকারটি নির্দিষ্ট করে দেখায় যদি টাইপটিতে কমা থাকে। তারা এটি টাইপফাইংও দেখায়। সুতরাং, আমি বিভ্রান্ত হয়ে পড়েছি, আমার কোডটিতে কী ভুল?
জেরে জোনস

17
কৌতূহলী, পুনরায় আকার বরাদ্দ রোধ করার জন্য ভেক্টরকে চাপ দেওয়া কি এই অর্থবোধ করে না?
অ্যালান

2
v.reserve(m.size())স্থানান্তরকালে ভেক্টরের পুনরায় আকার না দেওয়া এড়াতে ভুলবেন না ।
ব্রায়ান হোয়াইট

157
//c++0x too
std::map<int,int> mapints;
std::vector<int> vints;
vints.reserve(mapints.size());
for(auto const& imap: mapints)
    vints.push_back(imap.first);

4
খুশী হলাম। কথা ভুলে যান it = ...begin(); it != ...end। নিকস্ট অবশ্যই স্ট্যান্ডার্ড :: মানচিত্রে একটি পদ্ধতি কী () সেই ভেক্টরটি ফিরিয়ে
দিচ্ছে

2
@ বেহাইমার্স: আমার কাছে মনে হচ্ছে এই উত্তরটি দেওয়া হয়েছিল answered Mar 13 '12 at 22:33, যা সি ++ ১১ সি ++ হওয়ার কয়েক মাস পরে
সেবাস্তিয়ান মাচ

37
@ বেনহাইমার্স তবে এটি এখন যে প্রশ্নটি পড়ছেন তাদের পক্ষে এটি কার্যকর S
লুচিয়ান গ্রিগোর

9
(অটো এবং ইমপ) জন্য আরও সুনির্দিষ্ট কারণ কোনও অনুলিপি অপারেশন নেই।
হ্যালো ওয়ার্ল্ড

2
@ স্টুডেন্টটি, আরও ভাল for(auto const & imap : mapints),।
cp.engr

61

এই উদ্দেশ্যে একটি বুস্ট রেঞ্জ অ্যাডাপ্টার রয়েছে :

vector<int> keys;
// Retrieve all keys
boost::copy(m | boost::adaptors::map_keys, std::back_inserter(keys));

মানগুলি বের করার জন্য একই ধরণের মানচিত্রের_ রেঞ্জ অ্যাডাপ্টার রয়েছে।


1
দুর্ভাগ্যক্রমে, দেখে মনে হচ্ছে boost::adaptorsবুস্ট ১.৪৩ না হওয়া পর্যন্ত এটি উপলভ্য নয়। দেবিয়ানের বর্তমান স্থিতিশীল প্রকাশ (স্কুইজ) কেবলমাত্র 1.42
মিকৈল লে বেলিফকে

2
এটা সুন্দর. বুস্ট 1.42 স্কুইজের 2.5 বছর পূর্বে ফেব্রুয়ারী 2010 তে মুক্তি পেয়েছিল।
অ্যালিস্টায়ার

এই মুহুর্তে, আপডেটগুলি গ্রাহ্য করা উচিত নয় বা বা ব্যাকপোর্টস রেপোগুলি 1.44 বুস্ট দেওয়ার প্রস্তাব দিচ্ছে?
লুইস মাচুকা

কোন বুস্ট শিরোনাম এটি সংজ্ঞায়িত করা হয়?
জেমস ওয়েয়ারজবা

1
লিঙ্কযুক্ত ডকো দেখুন, এটি সংজ্ঞায়িত হয়েছেboost/range/adaptor/map.hpp
এলাস্টার

46

সি ++ 0 এক্স আমাদের আরও একটি দুর্দান্ত সমাধান দিয়েছেন:

std::vector<int> keys;

std::transform(
    m_Inputs.begin(),
    m_Inputs.end(),
    std::back_inserter(keys),
    [](const std::map<int,int>::value_type &pair){return pair.first;});

22
আমার দৃষ্টিতে এটি সম্পর্কে দুর্দান্ত কিছু নেই। std :: ভেক্টর <int> কী; keys.reserve (m_Inputs.size ()); (অটো কীভ্যালু: m_Inputs) for key.push_back (keyValue.first) জন্য; The ক্রিপ্টিক রূপান্তর চেয়ে অনেক ভাল। এমনকি পারফরম্যান্সের দিক থেকেও। এটা বরং ভালো.
জগন্নাথ

5
আপনি তুলনামূলক পারফরম্যান্স চাইলে আপনি এখানে কীগুলির আকার সংরক্ষণ করতে পারেন। আপনি যদি লুপের জন্য এড়াতে চান তবে ট্রান্সফর্মটি ব্যবহার করুন।
ড্যানডান

4
শুধু যুক্ত করতে চান - ব্যবহার করতে পারেন [] (
কনস্ট্যান্ড

@ আইভান.ুকর আপনি কোন সংকলকটি ব্যবহার করছেন? এই সিনট্যাক্সটি এখানে অনুমোদিত নয়: 'কনট কনট অটো &': প্যারামিটারে এমন কোনও ধরণের থাকতে পারে না যাতে 'অটো' থাকে
গোবে

4
ল্যাম্বডায় আইভান.ুকর অটো প্যারামিটারটি সি ++ ১৪
রোজল

16

@ ড্যানডানের উত্তর, সি ++ 11 ব্যবহার করা হ'ল:

using namespace std;
vector<int> keys;

transform(begin(map_in), end(map_in), back_inserter(keys), 
            [](decltype(map_in)::value_type const& pair) {
    return pair.first;
}); 

এবং সি ++ 14 ব্যবহার করে (@ আইভান.ুকর দ্বারা উল্লিখিত) আমরা এর decltype(map_in)::value_typeসাথে প্রতিস্থাপন করতে পারি auto


5
আপনি keys.reserve(map_in.size());দক্ষতা যোগ করতে পারে ।
গ্যালিক

আমি দেখতে পাই যে রূপান্তর পদ্ধতিটি আসলে লুপের চেয়ে বেশি কোড নেয়।
user1633272

কনস্টের পিছনে টাইপ করা যেতে পারে! আমি এটা প্রায় ভুলে গেছি।
ঝাং


10

আপনার সমাধানটি ভাল তবে আপনি এটি করতে একটি পুনরায় ব্যবহারকারীর ব্যবহার করতে পারেন:

std::map<int, int> m;
m.insert(std::pair<int, int>(3, 4));
m.insert(std::pair<int, int>(5, 6));
for(std::map<int, int>::const_iterator it = m.begin(); it != m.end(); it++)
{
    int key = it->first;
    int value = it->second;
    //Do something
}

10

@ মরিচা-পার্ক সমাধানের ভিত্তিতে, তবে সি ++ 17 তে:

std :: মানচিত্র <int, int> আইটেম;
std :: ভেক্টর <int> আইটেমকিজ;

(কনট অটো & [কী, উপেক্ষিত] আইটেমগুলি) এর জন্য
{
    itemKeys.push_back (কী);
}

আমি মনে করি না std::ignoreসিএ এভাবে স্ট্রাকচার্ড বাইন্ডিংয়ে ব্যবহার করা হবে। আমি একটি সংকলন ত্রুটি পেয়েছি। এটি কেবলমাত্র নিয়মিত পরিবর্তনশীল যেমন পর্যাপ্তরূপে ব্যবহার ignoredহয় না সেগুলি ব্যবহার করার পক্ষে পর্যাপ্ত হওয়া উচিত ।
জেবি

1
@ জেবি ধন্যবাদ প্রকৃতপক্ষে, কাঠামোগত বাইন্ডিংয়ের সাথে নয় তবে std::ignoreব্যবহারের জন্য std::tie। আমি আমার কোড আপডেট করেছি।
মদিয়ার

9

আমি মনে করি উপরে উপস্থাপিত BOOST_FOREach সুন্দর এবং পরিষ্কার, তবে, BOOST ব্যবহার করার পাশাপাশি আরও একটি বিকল্প রয়েছে।

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

std::map<int, int> m;
std::vector<int> keys;

using namespace boost::lambda;

transform(      m.begin(), 
                m.end(), 
                back_inserter(keys), 
                bind( &std::map<int,int>::value_type::first, _1 ) 
          );

copy( keys.begin(), keys.end(), std::ostream_iterator<int>(std::cout, "\n") );

ব্যক্তিগতভাবে, আমি মনে করি না যে এই পদ্ধতির ক্ষেত্রে BOOST_FOREach পদ্ধতির মতো পরিষ্কার নয়, তবে উত্সাহিত :: ল্যাম্বদা অন্যান্য ক্ষেত্রে সত্যিই পরিষ্কার হতে পারে।



7

একটি সি ++ 11 এর বিট নিন:

std::map<uint32_t, uint32_t> items;
std::vector<uint32_t> itemKeys;
for (auto & kvp : items)
{
    itemKeys.emplace_back(kvp.first);
    std::cout << kvp.first << std::endl;
}

5

আপনি বহুমুখী বুস্ট :: ট্রান্সফর্ম_লিটার ব্যবহার করতে পারেন। ট্রান্সফর্ম_িটরেটর আপনাকে পুনরাবৃত্ত মানগুলি রূপান্তর করতে দেয়, উদাহরণস্বরূপ আমাদের ক্ষেত্রে যখন আপনি কেবল কীগুলির সাথে ডিল করতে চান, মানগুলি না। Http://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/transfor_iterator.html# উদাহরণ দেখুন


5

সি ++ 11 জাদু ব্যবহার করে এখানে একটি দুর্দান্ত ফাংশন টেম্পলেট রয়েছে, এটি স্ট্যান্ড :: ম্যাপ, স্ট্যান্ড :: বিন্যস্ত_ ম্যাপ উভয়ের জন্যই কাজ করছে:

template<template <typename...> class MAP, class KEY, class VALUE>
std::vector<KEY>
keys(const MAP<KEY, VALUE>& map)
{
    std::vector<KEY> result;
    result.reserve(map.size());
    for(const auto& it : map){
        result.emplace_back(it.first);
    }
    return result;
}

এটি এখানে দেখুন: http://ideone.com/lYBzpL


4

সেরা অ-স্যাজি, অ-বৃদ্ধির এসটিএল সমাধান হ'ল মানচিত্রকে প্রসারিত করা: এর মতো পুনরাবৃত্তকারী:

template<class map_type>
class key_iterator : public map_type::iterator
{
public:
    typedef typename map_type::iterator map_iterator;
    typedef typename map_iterator::value_type::first_type key_type;

    key_iterator(const map_iterator& other) : map_type::iterator(other) {} ;

    key_type& operator *()
    {
        return map_type::iterator::operator*().first;
    }
};

// helpers to create iterators easier:
template<class map_type>
key_iterator<map_type> key_begin(map_type& m)
{
    return key_iterator<map_type>(m.begin());
}
template<class map_type>
key_iterator<map_type> key_end(map_type& m)
{
    return key_iterator<map_type>(m.end());
}

এবং তারপরে এগুলি ব্যবহার করুন:

        map<string,int> test;
        test["one"] = 1;
        test["two"] = 2;

        vector<string> keys;

//      // method one
//      key_iterator<map<string,int> > kb(test.begin());
//      key_iterator<map<string,int> > ke(test.end());
//      keys.insert(keys.begin(), kb, ke);

//      // method two
//      keys.insert(keys.begin(),
//           key_iterator<map<string,int> >(test.begin()),
//           key_iterator<map<string,int> >(test.end()));

        // method three (with helpers)
        keys.insert(keys.begin(), key_begin(test), key_end(test));

        string one = keys[0];

1
আমি এটি পাঠকের কাছে রেখে দেবো কনস্ট_টিরেটর তৈরি করতে এবং পুনরুদ্ধার পুনরাবৃত্তিগুলি প্রয়োজন হলে / প্রয়োজন হয়।
মারিয়াস

-1

পারমাণবিক মানচিত্রের উদাহরণ সহ

#include <iostream>
#include <map>
#include <vector> 
#include <atomic>

using namespace std;

typedef std::atomic<std::uint32_t> atomic_uint32_t;
typedef std::map<int, atomic_uint32_t> atomic_map_t;

int main()
{
    atomic_map_t m;

    m[4] = 456;
    m[2] = 45678;

    vector<int> v;
    for(map<int,atomic_uint32_t>::iterator it = m.begin(); it != m.end(); ++it) {
      v.push_back(it->second);
      cout << it->first << " "<<it->second<<"\n";
    }

    return 0;
}

-2

std::mapব্যবহারের দৃষ্টিকোণ থেকে সরলীকৃত এখানে উদাহরণগুলির একটির সাথে সামান্য মিল ।

template<class KEY, class VALUE>
std::vector<KEY> getKeys(const std::map<KEY, VALUE>& map)
{
    std::vector<KEY> keys(map.size());
    for (const auto& it : map)
        keys.push_back(it.first);
    return keys;
}

এটি ব্যবহার করুন:

auto keys = getKeys(yourMap);

2
আরে, আমি জানি এই উত্তরটি পুরানো তবে এটিও ভুল। আকার দিয়ে শুরু করার map.size()অর্থ ভেক্টরের আকারের দ্বিগুণ। অন্য কেউ মাথা ব্যাথা :( সংরক্ষণ করতে ঠিক করুন
thc

-3

(আমি সবসময়ই ভাবছি যে কেন std :: মানচিত্রে এটি করার জন্য কোনও সদস্য ফাংশন অন্তর্ভুক্ত নয়))

কারণ এটি আপনার চেয়ে ভাল আর এটি করতে পারে না। কোনও পদ্ধতির বাস্তবায়ন যদি কোনও ফ্রি ফাংশন বাস্তবায়নের চেয়ে সেরা না হয় তবে সাধারণভাবে আপনার কোনও পদ্ধতি রচনা করা উচিত নয়; আপনার একটি ফ্রি ফাংশন লেখা উচিত write

এটি যেভাবেই কার্যকর তা এটি অবিলম্বে পরিষ্কার হয় না clear


8
কোনও পদ্ধতি সরবরাহের জন্য লাইব্রেরির দক্ষতা ছাড়াও অন্যান্য কারণ রয়েছে যেমন "ব্যাটারি অন্তর্ভুক্ত" কার্যকারিতা এবং একটি সুসংগত, এনক্যাপসুলেটেড এপিআই। যদিও স্বীকৃতভাবে এই পদগুলির কোনওটিই এসটিএলকে বিশেষ করে বর্ণনা করে না: রে পরিষ্কার না কেন এটি দরকারী - সত্য? আমি মনে করি এটি উপলভ্য কীগুলি তালিকাভুক্ত করা একটি মানচিত্র / ডিক্টের সাথে করতে সক্ষম হওয়াই দরকারী জিনিস: এটি আপনি কী ব্যবহার করছেন তার উপর নির্ভর করে।
andybuckley

4
এই যুক্তি দ্বারা, আমাদের থাকা উচিত নয় empty()কারণ এটি হিসাবে কার্যকর করা যেতে পারে size() == 0
gd1

1
@ জিডি 1 যা বলেছে। যদিও কোনও শ্রেণিতে প্রচুর ক্রিয়ামূলক অপ্রয়োজনীয় হওয়া উচিত নয়, একেবারে শূন্যের উপর জোর দেওয়া ভাল ধারণা আইএমও নয় - কমপক্ষে সি ++ অবধি পদ্ধতিগুলিতে ফ্রি ফাংশনগুলিকে "আশীর্বাদ" করার অনুমতি না দেওয়া পর্যন্ত।
einpoklum

1
সি ++ এর পুরানো সংস্করণগুলিতে এমন পাত্রে ছিল যার জন্য খালি () এবং আকার () যথাযথভাবে বিভিন্ন পারফরম্যান্স গ্যারান্টি থাকতে পারে, এবং আমি মনে করি এটির অনুমতি দেওয়ার জন্য স্পেকটি যথেষ্ট looseিলা ছিল (বিশেষত, সংযুক্ত তালিকাগুলি যা ধ্রুবক-সময় বিভাজন () সরবরাহ করে) । যেমন, তাদের decoupling ইন্দ্রিয়গ্রাহ্য। তবে আমি মনে করি না এই তাত্পর্যটিকে আর অনুমোদিত হয়।
ড্রিপজ্জা

আমি রাজী. সি ++ std::map<T,U>জোড়াগুলির পাত্র হিসাবে বিবেচনা করে । পাইথনে, dictপুনরাবৃত্তি হওয়ার সময় এর কীগুলির মতো কাজ করে তবে আপনাকে d.items()C ++ আচরণ পেতে বলতে দেয় । পাইথনও সরবরাহ করে d.values()std::map<T,U>অবশ্যই একটি প্রদান করতে পারে keys()এবং values()পদ্ধতি যা একটি বস্তু আছে যা আসতে begin()এবং end()যে iterators কী ও মান উপর প্রদান।
বেন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.