সি ++ মানচিত্রে কীগুলি সনাক্ত করুন


121

কীগুলির মাধ্যমে পুনরাবৃত্তি করার কোনও উপায় আছে, কোনও সি ++ মানচিত্রের জোড়া নয়?


মানগুলিতে পুনরাবৃত্তি পাওয়ার ধারণাটি এটি এসটিএল অ্যালগরিদমে ব্যবহার করা হয়, উদাহরণস্বরূপ, দুটি মানচিত্রের চাবি ছেদ করা। বুস্টের সাথে জড়িত সমাধান এটির অনুমতি দেয় না কারণ এটি একটি বুস্ট পুনরুক্তি তৈরি করবে। সবচেয়ে খারাপ উত্তর সবচেয়ে বেশি ভোট পায়!

উত্তর:


70

"সত্যিকারের" পুনরাবৃত্তির ফিরে আসা মানটি যদি আপনার সত্যই লুকিয়ে রাখতে হয় (উদাহরণস্বরূপ আপনি স্ট্যান্ডার্ড অ্যালগরিদমের সাহায্যে আপনার কী-পুনরুক্তি করতে চান, যাতে তারা জোড়গুলির পরিবর্তে কীগুলিতে কাজ করে) তবে বুস্টের দিকে একবার নজর দিন transform_iterator

[টিপ: একটি নতুন শ্রেণীর জন্য বুস্ট ডকুমেন্টেশন দেখার সময়, প্রথমে "উদাহরণগুলি" পড়ুন। তারপরে আপনার কাছে পৃথিবীর অন্যান্য অংশগুলি কী সম্পর্কে কথা বলছে তা নির্ধারণের একটি স্পোর্টস সুযোগ রয়েছে:]


2
বুস্টের সাহায্যে আপনি BOOST_FOREach (কনট কী_ট কী, the_map | বুস্ট :: অ্যাডাপ্টারস: ম্যাপ_কিজ) লিখতে পারেন something কিছু করুন} boost.org/doc/libs/1_50_0/libs/range/doc/html/range/references/…
রড্রিগব

120

মানচিত্রটি সহকারী ধারক। অতএব, পুনরাবৃত্তি হ'ল একজোড়া কী, ভাল। যদি আপনার কেবল কীগুলির দরকার হয় তবে আপনি জোড়া থেকে মান অংশটি উপেক্ষা করতে পারেন।

for(std::map<Key,Val>::iterator iter = myMap.begin(); iter != myMap.end(); ++iter)
{
Key k =  iter->first;
//ignore value
//Value v = iter->second;
}

সম্পাদনা করুন: আপনি যদি কেবল বাইরের কীগুলিই প্রকাশ করতে চান তবে আপনি মানচিত্রটিকে ভেক্টর বা কীতে রূপান্তর করতে পারবেন এবং প্রকাশ করতে পারবেন।


তবে তারপরে ভেক্টরের পুনরুক্তি বহির্ভূত করা সত্যিই খারাপ ধারণা হবে।
নবীন

পুনরুক্তিকারীটি প্রকাশ করবেন না। কেবল ভেক্টরে কীগুলি সরবরাহ করুন
এজে।

5
পরিবর্তে আপনি এটি করতে চাইতে পারেন: const Key& k(iter->first);
স্ট্রাইক্লি

17
দুটি জিনিস, এই ঠিক উত্তর তিনি ইতিমধ্যেই জানতেন এবং, আপনি ভালো কিছু কাজ করতে চান দ্বিতীয়ত এই পদ্ধতি আপনাকে সাহায্য করবে না খুঁজছেন ছিল না সঙ্গে ওপি এর প্রশ্নের উত্তর: std::vector<Key> v(myMap.begin(), myMap.end())
আন্দ্রেয়াস ম্যাগনসন

কীগুলিকে কোনও ভেক্টরে রূপান্তর করবেন না। একটি নতুন ভেক্টর তৈরি করা পুনরাবৃত্তির উদ্দেশ্যকে পরাস্ত করে, যা বলে মনে হয় দ্রুত এবং কোনও কিছু বরাদ্দ নয়। এছাড়াও, এটি বড় সেটগুলির জন্য ধীর হবে।
কেভিন চেন

85

সি ++ 11 দিয়ে পুনরাবৃত্তির বাক্য গঠন সহজ is আপনি এখনও জোড়ায় পুনরাবৃত্তি করেন তবে কেবল কীটি অ্যাক্সেস করা সহজ।

#include <iostream>
#include <map>

int main()
{
    std::map<std::string, int> myMap;

    myMap["one"] = 1;
    myMap["two"] = 2;
    myMap["three"] = 3;

    for ( const auto &myPair : myMap ) {
        std::cout << myPair.first << "\n";
    }
}

29
মূল প্রশ্নটি স্পষ্টভাবে "জোড় নয়" বলে says
আয়ান

41

বুস্ট ছাড়াই

আপনি এই মানচিত্রের জন্য কেবল এসটিএল পুনরায় প্রসারিত করে এটি করতে পারেন। উদাহরণস্বরূপ, ইনটগুলিতে স্ট্রিংয়ের ম্যাপিং:

#include <map>
typedef map<string, int> ScoreMap;
typedef ScoreMap::iterator ScoreMapIterator;

class key_iterator : public ScoreMapIterator
{
  public:
    key_iterator() : ScoreMapIterator() {};
    key_iterator(ScoreMapIterator s) : ScoreMapIterator(s) {};
    string* operator->() { return (string* const)&(ScoreMapIterator::operator->()->first); }
    string operator*() { return ScoreMapIterator::operator*().first; }
};

আপনি এই টেম্পলেটটিতে এই এক্সটেনশনটি সম্পাদন করতে পারেন আরও সাধারণ সমাধানের জন্য কোনও ।

ঠিক মত আপনি, একটি তালিকা পুনরুক্তিকারীর ব্যবহার করেন ব্যতীত আপনি iterating মানচিত্রের উপর করছি আপনি আপনার পুনরুক্তিকারীর ব্যবহার begin()এবং end()

ScoreMap m;
m["jim"] = 1000;
m["sally"] = 2000;

for (key_iterator s = m.begin(); s != m.end(); ++s)
    printf("\n key %s", s->c_str());

16
+1: অবশেষে, "জোড়গুলি নয়" বিট পড়েছেন এমন কেউ! চিয়ার্স, এটি আমার অনুমানের মাধ্যমে খননের সময় সাশ্রয় করেছে!
কে কে কোয়ান

1
এবং পরীক্ষিত সমাধানের নীচে, এবং আমি মান পুনরাবৃত্তকারী যুক্ত করেছি added
degski

আমার প্রশ্ন থেকে আপনার প্রশ্ন যুক্ত।
আয়ান

template<typename C> class key_iterator : public C::iterator, ইত্যাদি
গ্যাব্রিয়েল

38

সি ++ 17 এর সাহায্যে আপনি লুপের জন্য একটি পরিসীমা-ভিত্তিক স্ট্রাকচার্ড বাইন্ডিং ব্যবহার করতে পারেন ( সেই অনুযায়ী জন এইচ এর উত্তর অভিযোজিত ):

#include <iostream>
#include <map>

int main() {
    std::map<std::string, int> myMap;

    myMap["one"] = 1;
    myMap["two"] = 2;
    myMap["three"] = 3;

    for ( const auto &[key, value]: myMap ) {
        std::cout << key << '\n';
    }
}

দুর্ভাগ্যক্রমে সি ++ 17 স্ট্যান্ডার্ডের আপনাকে valueভেরিয়েবল ঘোষণা করতে হবে , যদিও আপনি এটি ব্যবহার করছেন না ( std::ignoreযেহেতু এটি ব্যবহার করবে std::tie(..)না তেমন কার্যকর হয় না, এই আলোচনা দেখুন) )।

কিছু সংকলক অপ্রয়োজনীয় valueভেরিয়েবল সম্পর্কে আপনাকে সতর্ক করতে পারে ! অব্যবহৃত ভেরিয়েবল সম্পর্কিত সংকলন -কালীন সতর্কতাগুলি আমার মনে যে কোনও প্রোডাকশন কোডের জন্য যেতে হবে না। সুতরাং, এটি নির্দিষ্ট সংকলক সংস্করণের জন্য প্রযোজ্য নাও হতে পারে।


আপনি এটি নূতন নীতি অবহেলা করতে পারেন? এটি কি সংকলিত কোডটিতে দক্ষতার ক্ষতি করবে বা আসলে কিছুই মূল্যায়ন করবে? (আমি বাঁধাইয়ের অর্থ নয় বরং লুপের মধ্যে থাকা একটি ক্রিয়া হিসাবে)
কোটোরশিনটো

যেহেতু সি ++ 17 আপনি [[সম্ভবত_উক্তউক্ত]] ব্যবহার করতে পারেন। এটি সতর্কতা দমন করে। এটি পছন্দ করুন:for ([[maybe_unused]] const auto &[key, v_not_used] : my_map) { use(key); }
আরুয়াচো

15

আরও সাধারণ টেম্পলেটযুক্ত সমাধানের নীচে যা ইয়ান উল্লেখ করেছে ...

#include <map>

template<typename Key, typename Value>
using Map = std::map<Key, Value>;

template<typename Key, typename Value>
using MapIterator = typename Map<Key, Value>::iterator;

template<typename Key, typename Value>
class MapKeyIterator : public MapIterator<Key, Value> {

public:

    MapKeyIterator ( ) : MapIterator<Key, Value> ( ) { };
    MapKeyIterator ( MapIterator<Key, Value> it_ ) : MapIterator<Key, Value> ( it_ ) { };

    Key *operator -> ( ) { return ( Key * const ) &( MapIterator<Key, Value>::operator -> ( )->first ); }
    Key operator * ( ) { return MapIterator<Key, Value>::operator * ( ).first; }
};

template<typename Key, typename Value>
class MapValueIterator : public MapIterator<Key, Value> {

public:

    MapValueIterator ( ) : MapIterator<Key, Value> ( ) { };
    MapValueIterator ( MapIterator<Key, Value> it_ ) : MapIterator<Key, Value> ( it_ ) { };

    Value *operator -> ( ) { return ( Value * const ) &( MapIterator<Key, Value>::operator -> ( )->second ); }
    Value operator * ( ) { return MapIterator<Key, Value>::operator * ( ).second; }
};

সমস্ত ক্রেডিট আয়ানের দিকে যায় ... ধন্যবাদ ইয়ান।



5

বুস্টের ট্রান্সফর্ম_পিটর ব্যবহার করে এটি কীভাবে করা যায় তার একটি উদাহরণ এখানে

#include <iostream>
#include <map>
#include <iterator>
#include "boost/iterator/transform_iterator.hpp"

using std::map;
typedef std::string Key;
typedef std::string Val;

map<Key,Val>::key_type get_key(map<Key,Val>::value_type aPair) {
  return aPair.first;
}

typedef map<Key,Val>::key_type (*get_key_t)(map<Key,Val>::value_type);
typedef map<Key,Val>::iterator map_iterator;
typedef boost::transform_iterator<get_key_t, map_iterator> mapkey_iterator;

int main() {
  map<Key,Val> m;
  m["a"]="A";
  m["b"]="B";
  m["c"]="C";

  // iterate over the map's (key,val) pairs as usual
  for(map_iterator i = m.begin(); i != m.end(); i++) {
    std::cout << i->first << " " << i->second << std::endl;
  }

  // iterate over the keys using the transformed iterators
  mapkey_iterator keybegin(m.begin(), get_key);
  mapkey_iterator keyend(m.end(), get_key);
  for(mapkey_iterator i = keybegin; i != keyend; i++) {
    std::cout << *i << std::endl;
  }
}

4

যখন কোনও স্পষ্ট beginএবং endপ্রয়োজন হয় না, যেমন পরিসর-লুপিংয়ের জন্য, লুপ ওভার কীগুলি (প্রথম উদাহরণ) বা মানগুলি (দ্বিতীয় উদাহরণ) এর সাথে পাওয়া যায়

#include <boost/range/adaptors.hpp>

map<Key, Value> m;

for (auto k : boost::adaptors::keys(m))
  cout << k << endl;

for (auto v : boost::adaptors::values(m))
  cout << v << endl;


3

আপনি এটি করতে চান?

std::map<type,type>::iterator iter = myMap.begin();
std::map<type,type>::iterator iter = myMap.end();
for(; iter != endIter; ++iter)
{
   type key = iter->first;  
   .....
}

হ্যাঁ, আমি জানি, সমস্যাটি আমার একটি ক্লাস এ {সার্বজনীন: // আমি এখানে ব্যক্তিগত মানচিত্রের কীগুলির দ্বারা একটি পুনরাবৃত্তিকে প্রকাশ করতে চাই ব্যক্তিগত: মানচিত্র <>};
বোগদান বালান

সেক্ষেত্রে আমি মনে করি আপনি std :: trasnform ব্যবহার করে এবং মানচিত্র থেকে কেবল কীগুলি বাছাই করে একটি std :: তালিকা তৈরি করতে পারেন। তারপরে আপনি তালিকার পুনরাবৃত্তিকে প্রকাশ করতে পারেন কারণ তালিকায় আরও উপাদান সন্নিবেশ করানো বিদ্যমান পুনরাবৃত্তিকে অকার্যকর করবে না।
নবীন

3

আপনার যদি এমন একটি পুনরুত্থানকারী প্রয়োজন যা কেবলমাত্র আপনার নিজের শ্রেণিতে মানচিত্রের পুনরাবৃত্তি মোড়ানোর জন্য প্রয়োজনীয় কীগুলি ফেরত দেয় যা পছন্দসই ইন্টারফেস সরবরাহ করে। আপনি এখানে নতুন স্ক্র্যাচ থেকে নতুন পুনরায় শ্রেণীর ক্লাস ঘোষণা করতে পারেন, বিদ্যমান সহায়ক সহায়িকা ব্যবহারের জন্য। এই উত্তরটি দেখায় যে কীভাবে বুস্টকে কীভাবে transform_iteratorপুনরাবৃত্তকারীকে মোড়ক ব্যবহার করতে হয় যা কেবলমাত্র মান / কীগুলি দেয়।


2

আপনি পারে

  • একত্রিত করে একটি কাস্টম পুনরাবৃত্তকারী শ্রেণি তৈরি করুন std::map<K,V>::iterator
  • ব্যবহারের std::transformআপনার এর map.begin()জন্য map.end() একটি সঙ্গে boost::bind( &pair::second, _1 )functor
  • লুপ ->secondদিয়ে পুনরুক্তি করার সময় কেবল সদস্যটিকে উপেক্ষা করুন for

2

এই উত্তরটি রডরিববের মতো, বাদে BOOST_FOREACH। পরিবর্তে এর জন্য আপনি সি ++ এর ব্যাপ্তি ব্যবহার করতে পারেন।

#include <map>
#include <boost/range/adaptor/map.hpp>
#include <iostream>

template <typename K, typename V>
void printKeys(std::map<K,V> map){
     for(auto key : map | boost::adaptors::map_keys){
          std::cout << key << std::endl;
     }
}

0

বুস্ট ব্যতীত আপনি এটি এটি করতে পারেন। এটি ভাল হবে যদি আপনি getKeyIterator () এর পরিবর্তে একটি কাস্টার অপারেটর লিখতে পারেন তবে আমি এটি সংকলন করতে পারি না।

#include <map>
#include <unordered_map>


template<typename K, typename V>
class key_iterator: public std::unordered_map<K,V>::iterator {

public:

    const K &operator*() const {
        return std::unordered_map<K,V>::iterator::operator*().first;
    }

    const K *operator->() const {
        return &(**this);
    }
};

template<typename K,typename V>
key_iterator<K,V> getKeyIterator(typename std::unordered_map<K,V>::iterator &it) {
    return *static_cast<key_iterator<K,V> *>(&it);
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::unordered_map<std::string, std::string> myMap;
    myMap["one"]="A";
    myMap["two"]="B";
    myMap["three"]="C";
    key_iterator<std::string, std::string> &it=getKeyIterator<std::string,std::string>(myMap.begin());
    for (; it!=myMap.end(); ++it) {
        printf("%s\n",it->c_str());
    }
}

0

উত্তরোত্তর জন্য, এবং যেহেতু আমি একটি পরিসীমা তৈরির উপায় অনুসন্ধান করার চেষ্টা করছিলাম, তাই বিকল্পটি হ'ল :: অ্যাডাপ্টার :: ট্রান্সফর্ম ব্যবহার করা

এখানে একটি ছোট উদাহরণ:

#include <boost/range/adaptor/transformed.hpp>
#include <iostream>
#include <map>

int main(int argc, const char* argv[])
{
  std::map<int, int> m;
  m[0]  = 1;
  m[2]  = 3;
  m[42] = 0;

  auto key_range =
    boost::adaptors::transform(
      m,
      [](std::map<int, int>::value_type const& t) 
      { return t.first; }
    ); 
  for (auto&& key : key_range)
    std::cout << key << ' ';
  std::cout << '\n';
  return 0;
}

আপনি যদি মানগুলি নিয়ে পুনরাবৃত্তি করতে চান t.secondতবে ল্যাম্বডায় ব্যবহার করুন।


0

এখানে প্রচুর ভাল উত্তর, নীচে তাদের কয়েকটি ব্যবহার করে এমন একটি পদ্ধতির সাহায্য দেওয়া হয়েছে যা আপনাকে এটি লিখতে দেয়:

void main()
{
    std::map<std::string, int> m { {"jim", 1000}, {"sally", 2000} };
    for (auto key : MapKeys(m))
        std::cout << key << std::endl;
}

আপনি যদি সর্বদা এটি চেয়েছিলেন তবে ম্যাপকি () এর কোড এখানে রয়েছে:

template <class MapType>
class MapKeyIterator {
public:
    class iterator {
    public:
        iterator(typename MapType::iterator it) : it(it) {}
        iterator operator++() { return ++it; }
        bool operator!=(const iterator & other) { return it != other.it; }
        typename MapType::key_type operator*() const { return it->first; }  // Return key part of map
    private:
        typename MapType::iterator it;
    };
private:
    MapType& map;
public:
    MapKeyIterator(MapType& m) : map(m) {}
    iterator begin() { return iterator(map.begin()); }
    iterator end() { return iterator(map.end()); }
};
template <class MapType>
MapKeyIterator<MapType> MapKeys(MapType& m)
{
    return MapKeyIterator<MapType>(m);
}

0

আমি সমস্ত মানচিত্রের ধরণের সাথে কাজ করার জন্য আয়ানের উত্তর গ্রহণ করেছি এবং এর জন্য কোনও রেফারেন্স ফিরিয়ে দেওয়া ঠিক করেছি operator*

template<typename T>
class MapKeyIterator : public T
{
public:
    MapKeyIterator() : T() {}
    MapKeyIterator(T iter) : T(iter) {}
    auto* operator->()
    {
        return &(T::operator->()->first);
    }
    auto& operator*()
    {
        return T::operator*().first;
    }
};

-1

আমি জানি এটি আপনার প্রশ্নের উত্তর দেয় না, তবে আপনি যে বিকল্পটি দেখতে চাইতে পারেন তা হ'ল একই সূচকটির সাথে দুটি ভেক্টর রয়েছে যা "লিঙ্কযুক্ত" তথ্যযুক্ত ..

সুতরাং ..

std::vector<std::string> vName;

std::vector<int> vNameCount;

আপনি যদি নাম অনুসারে নামের গণনা চান তবে আপনি কেবলমাত্র vName.size () এর লুপের জন্য আপনার দ্রুত কাজটি করতে পারেন এবং যখন আপনি এটি খুঁজে পেয়েছেন যে আপনি vNameCount এর জন্য সূচক।

অবশ্যই এটি আপনাকে মানচিত্রের সমস্ত কার্যকারিতা না দেয় এবং নির্ভর করে আরও ভাল হতে পারে বা না পারে তবে আপনি কীগুলি জানেন না, এবং খুব বেশি প্রসেসিং যুক্ত না করা সহজ be

কেবল মনে রাখবেন আপনি যখন একটি থেকে যুক্ত / মুছবেন তখন আপনাকে অন্যটি থেকে এটি করতে হবে বা জিনিসগুলি পাগল হয়ে উঠবে হে: পি

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