473,804 Members | 3,674 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

getting keys out of a map

Hi

Is there a simple general way of getting the keys out of a map? Or a vector of
pairs?

My problem seems to be that the pair<> type returned by iterating through either
has no methods to bind to to get the .first or .second elements. That seems to
me to be a major oversight - so I am assuming I must be making one!

For instance, imagine I want to use eg accumulate, to add up all the keys in a
map:
template<class A, class B>
struct FirstOfPair : public unary_function< const pair<A, B>, A> {
A operator()(cons t pair<A, B>& p) { return p.first; }
};

template<class A, class B>
struct AccumulatePairF irsts : public binary_function <A, const pair<A, B>, A> {
A operator()(A a, const pair<A, B>& p) { return a + FirstOfPair<A,B >()(p); }
};

int sumKeys(const map<int, string>& m) {
return accumulate(m.be gin(), m.end(), 0,
AccumulatePairF irsts<int, string>());
}
This is pretty horrendous! It took me about 20 goes to get this all right. Also
I am not happy that I had to define AccumulatePairF irsts - couldnt I bind (or
compose?) with plus<int>() here?

Calling any gurus, please help!

I have a not-totally-weak functional background btw; I just often find it hard
to see how to do simple things using C++'s 'way'.

Cheers

Paul.
Jul 19 '05 #1
4 7735

"Paul MG" <pa****@digital brain.com> wrote in message
news:26******** *************** **@posting.goog le.com...
Hi

Is there a simple general way of getting the keys out of a map? Or a vector of pairs?

My problem seems to be that the pair<> type returned by iterating through either has no methods to bind to to get the .first or .second elements. That seems to me to be a major oversight - so I am assuming I must be making one!

For instance, imagine I want to use eg accumulate, to add up all the keys in a map:
template<class A, class B>
struct FirstOfPair : public unary_function< const pair<A, B>, A> {
A operator()(cons t pair<A, B>& p) { return p.first; }
};

template<class A, class B>
struct AccumulatePairF irsts : public binary_function <A, const pair<A, B>, A> { A operator()(A a, const pair<A, B>& p) { return a + FirstOfPair<A,B >()(p); } };

int sumKeys(const map<int, string>& m) {
return accumulate(m.be gin(), m.end(), 0,
AccumulatePairF irsts<int, string>());
}
This is pretty horrendous! It took me about 20 goes to get this all right. Also I am not happy that I had to define AccumulatePairF irsts - couldnt I bind (or compose?) with plus<int>() here?

Calling any gurus, please help!

I have a not-totally-weak functional background btw; I just often find it hard to see how to do simple things using C++'s 'way'.

---snip---

#include <iostream>
#include <algorithm>
#include <string>
#include <map>

struct accumulate {
int& total;
accumulate(int& total_) : total(total_) { }
void operator()(cons t std::pair<int, std::string> &p) { total +=
p.first; }
};

int main(int argc, char* argv[])
{
std::map<int, std::string> foo;

foo[3] = "hello";
foo[6] = "world";

int total = 0;
for_each(foo.be gin(), foo.end(), accumulate(tota l));

std::cout << "key total = " << total << std::endl;
return 0;
}

---snip---
Cheers

Paul.


--
Roger
Jul 19 '05 #2
On 24 Jul 2003 14:16:41 -0700, pa****@digitalb rain.com (Paul MG)
wrote:
Hi

Is there a simple general way of getting the keys out of a map? Or a vector of
pairs?

My problem seems to be that the pair<> type returned by iterating through either
has no methods to bind to to get the .first or .second elements. That seems to
me to be a major oversight - so I am assuming I must be making one!

For instance, imagine I want to use eg accumulate, to add up all the keys in a
map:
template<class A, class B>
struct FirstOfPair : public unary_function< const pair<A, B>, A> {
A operator()(cons t pair<A, B>& p) { return p.first; }
};

template<class A, class B>
struct AccumulatePairF irsts : public binary_function <A, const pair<A, B>, A> {
A operator()(A a, const pair<A, B>& p) { return a + FirstOfPair<A,B >()(p); }
};

int sumKeys(const map<int, string>& m) {
return accumulate(m.be gin(), m.end(), 0,
AccumulatePairF irsts<int, string>());
}
This is pretty horrendous! It took me about 20 goes to get this all right. Also
I am not happy that I had to define AccumulatePairF irsts - couldnt I bind (or
compose?) with plus<int>() here?

Calling any gurus, please help!

I have a not-totally-weak functional background btw; I just often find it hard
to see how to do simple things using C++'s 'way'.


If you must use algorithms, then you should either use iterator
adaptors or lambda functions. e.g.

To write an iterator adaptor that projects an iterator onto the first
member of a pair (or use the projection iterator with a suitable
functor):
http://www.boost.org/libs/utility/iterator_adaptors.htm

Using boost.lambda: http://www.boost.org/libs/lambda/doc/index.html

#include <map>
#include <string>
#include <numeric>
#include <iostream>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

int main()
{

using namespace boost::lambda;
typedef std::map<int, std::string> m_t;
typedef m_t::value_type pair_t;
m_t m;
m[4] = "Foo";
m[2] = "Bar";
int result = std::accumulate (
m.begin(),
m.end(),
0,
_1 + bind(&pair_t::f irst, _2)
);
std::cout << result << '\n';
}

Without a toolkit like boost.lambda handy, the for loop definitely
wins in cases like this, and even with boost.lambda, the increase in
compile times might not be worth it.

Tom
Jul 19 '05 #3

"Paul MG" <pa****@digital brain.com> wrote in message
news:26******** *************** ***@posting.goo gle.com...
Thanks for your thoughts guys.

There seem to be two major threads of response:

1) Use C (ie explicit loops). I realise that this can be a tradeoff worth making, I just wanted to push a little harder toward StlStyle to see if we could come up something nicer.

2) Don't use std::accumulate () to do your accumulation, use std::for_each() and a bespoke functor. A neat solution I agree but it bugs me not to use std::accumulate () to accumulate a range.

What I think I want to be able to do though, is something like:

int sumKeys(const map<int, string>& m) {
return accumulate(m.be gin(), m.end(), 0,
someBinding(plu s<int>,
mem_fun_ref(&pa ir<int, string>::first) ) );
}

Because it seems more expressive of intent. It says

return the *accumulation* of *m* *adding up* the *first* of each element.
Rather than

initialize an accumulator variable to zero
initialize an iterator to the first element of *m*
while that iterator is not at the last element of *m*
add the *first* of the pointed-at element to my accumulator variable
increment that iterator
return the value of my accumulator variable

See how sparse the actual algorithm core is amongst all the surrounding stuff in the second version?

Obviously I am biased here, perhaps someone else would like to write out the two 'scripts' and somehow show that an alternative to my version is more
expressive?

Of course, there is the slight problem that I haven't quite worked out what someBinder() is in my solution ;). That's what I'm posting to find out I guess!
Because (as you pointed out in your original post) std::pair doesn't define
member functions to access
its member variables, the mem_fun and mem_fun_ref helpers don't help, so I
don't think this can be
done as a one-liner.

Once you've defined the symantics of adding a pair<int, string> to an int,
however, it's all rather easy:

---snip---

namespace std {
inline int operator+(const int& acc, const std::pair<int, std::string>&
p) {
return acc + p.first;
}
}

std::map<int, std::string> foo;

int total = std::accumulate (foo.begin(), foo.end(), 0);

---snip---
thanx for feedback,

paul.


--
Roger
Jul 19 '05 #4
Thanks tom_usenet, it was interesting to see the solution using
boost::lambda.

I am currently perusing boost's iterator adaptor library too. Thanks
for the link.

I have since realised what I 'need' to solve my original problem as
stated:

1) pair<> to have functions for first and second which you can
bind against

2) arbitrary function compose()rs which can build a 'tree' of
functions, leading from args to return type, rather than
just the 'pipeline' provided by compose1() etc.

In reference to (1), are there good justifications for why these don't
exist? It just makes you write your own functors FirstOfPair<> and
SecondOfPair<> to do it. I have always accepted that 'public data is
evil, prefer private data and public accessors'; can anybody explain
why this is an exceptional case?

In reference to (2)... Well, possibly I am just barking up the wrong
tree entirely. I think that is what the general feel of the feedback
has been!

But I managed to create a sort of tree-like compose(), to do what I
want. Here it is:

// Constraint: UnOp::result_ty pe == BinOp::second_a rgument_type
template<class BinOp, class UnOp>
class MyBinder2nd : public
binary_function <typename BinOp::first_ar gument_type,
typename UnOp::argument_ type,
typename BinOp::result_t ype> {
protected:
BinOp binOp;
UnOp unOp;
public:
MyBinder2nd(con st BinOp& b, const UnOp& u)
: binOp(b), unOp(u) {}

result_type operator() (
const first_argument_ type& x,
const second_argument _type& y)
{
return binOp(x, unOp(y));
}
};

template<class BinOp, class UnOp>
MyBinder2nd<Bin Op, UnOp> MyBind2nd(const BinOp& b,
const UnOp& u)
{
return MyBinder2nd<Bin Op, UnOp>(b, u);
}

I feel I could enforce that 'Constraint' somehow using template
templates (could I?)

My main problem is that I couldn't think of a sensible name.
TreeCompose is just silly. MyBind2nd is cos it is like bind2nd but
takes a unary_function instead of a fixed value to bind against the
second arg.

A secondary problem is that this seems to be very specific: what about
building arbitrary trees of function calls? is that hard? impossible?
(given the non-availability of variable-length template-arg lists).

Anyway, my client code now looks like this:

int f(const map<int, string>& m) {
return accumulate(m.be gin(), m.end(), 0,
MyBind2nd(plus< int>(),
FirstOfPair<int , string>()));
}

which is acceptable I think? Tho it seems a pain that I have to
declare all those template params, is there any way they could be
inferred?

------------

I am surprised no-one has said this yet, so I will say it myself:
"trying to program Lisp/Haskell in C++ is just stupid."

I accept that initially, what I have trouble with is when it is
sensible to use a functional, declarative style in solving a problem
in C++, and when to revert to an imperative, procedural style. The
literature appears to draw the line 'when it looks messy'. But this is
too subjective - many people think even a simple use of for_each more
'messy' than a simple for-loop. If declarative is good, surely it
should be good all the way up?

Another way of formulating my point is,

1. There exist some arguments which justify preferring a
for_each call over a simple for loop.
2. Some people reject those arguments with counterargument s.

Therefore if you reject my attempts to use STL rather than a loop in
this case, using the arguments from (2), can I not just respond with
the arguments from (1)? How is the situation different?

Any illuminating thoughts here would be much appreciated. :)

Thanks for your help,

Paul.
Jul 19 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
13064
by: Lachlan Hunt | last post by:
Hi, I've been looking up lots of documentation and trying to work out a cross-platform method of capturing a keyboard event and working out which key was pressed. From what I can find, there doesn't appear to be any standardised keyboard event interface other than this DOM 3 Events W3C Working Group Note . However, it is only a note and doesn't appear to be implemented in any browser. Is there another standard that I've missed? The...
8
59520
by: SenthilVel | last post by:
how to get the corresponding values for a given Key in hashtable ??
6
6937
by: kurotsuke | last post by:
Hi, I'm trying to use the GetKeyName API to get the name of certain keys (in the system language). For example the names of SHIFT and RETURN keys as well as the names of same special characters. I tried to call the API GetKeyName passing the KeyCode of the KeyUP event but got no result
2
1576
by: Mark | last post by:
In this article http://support.microsoft.com/?id=329290 I will have to perform this in my installation. The question is since the aspnet_setreg.exe does not automatically grant the asp.net service user name to the registry entries how can I find the username the aps.net service is running under so that I can programmatically grant this user access to the registry keys created? You would think the aspnet_setreq.exe would finish off the...
1
1300
by: tmp | last post by:
I have the following problem: 1) I have one master table with a primary key. 2) In addition I have *several* slave tables, all refering to a primary key in the master table (no two slave tables refer to the same master key) I wan't to make sure that no keys in the master table are unreferred, that is:
0
1753
by: =?Utf-8?B?cGI2NDgxNzQ=?= | last post by:
We have been having this problem for months and always assumed it was because of our somewhat complicated setup. I have just spent almost all of today making this into a simple example that can be easily reproduced and it seems like a major .NET flaw/limitation that I was hoping you could explain to me as it is really frustrating me. I just want to be able to get info for a row clicked, whether it is a Repeater, GridView, etc. I have...
1
11012
by: apax999 | last post by:
Kinda new to SQL, using SQL Server 2005. I have some foreign keys in a couple of tables. I need to drop these tables, but can't since I'll get the error: Msg 3726, Level 16, State 1, Line 1 Could not drop object 'Client' because it is referenced by a FOREIGN KEY constraint.
1
3982
by: bhavanirayala | last post by:
Hi, I am sending the values from one method to another method to get the values from xml file based on the inputs. I am getting the error like:: Variable "$collType" will not stay shared Variable "$collState" will not stay shared at line 77. please see the below code and help me out.
2
1423
by: kriz4321 | last post by:
Hi I have a array in which I need to count the number of ocurrence of a particular word for eg I need to count no of times a word "test" , "test2" occurs in a array @list. (The contents of the array is around 100 lines) Code: open(FH3, "sample.txt"); while(<FH3>)
0
9704
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9572
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10562
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10319
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10303
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
7608
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6845
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5508
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
4282
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.