Comparing elements in map to each other

My task is to find the node that is closest to the specified node in distance, but I am unsure how to compare elements in a map to each other to do the following.

Basically, my function Node Network::closest(Node &n) should go through all the nodes in my map and find the one that is closest distance wise and then give the Euclidean Distance, which I have already have calculating in a different function called double Node::distance (const Node& n) const . So, for the given node n return the closest node in the network (excluding n itself) in terms of Euclidean distance.

Here's what I have code wise:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct Network{
  string label;
  map<string, Node> nodes;
  vector<string> route;

  Network()=default;
  Network(ifstream &);
  string to_string () const;
  Node get_node(string);
  void put_node(Node);
  bool in_route(const Node&);
  Node closest(Node &);
  string calculate_route(const Node&, const Node&);
};


1
2
3
4
5
6
7
8
9
10
11
12
double Node::distance (const Node& n) const {
	
    double xcoord = x - n.x;
    double ycoord = y - n.y;
    double distancecalc;
    double result;
     
    distancecalc = pow(xcoord, 2) + pow(ycoord, 2);
    result = sqrt(distancecalc);
     
    return result;
}


1
2
3
4
5
6
Node Network::get_node(string str) {
	
	Node result;
	result = nodes.at(str);
	return result;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
string Network::to_string () const {

	string output;
	string result;
	
	for(auto itr = nodes.cbegin(); itr != nodes.cend(); itr++) {
		Node n = itr->second;
		
		output += n.to_string() + ", ";
	}
	
	result = output.substr(0, output.size() - 2 );
	
	return result;
}


This is what is called in main:
1
2
3
4
5
6
7
8
 string fname;
    cin >> fname;
    ifstream fin(fname);
    Network net(fin);
    auto n = net.get_node("A");
    auto close = net.closest(n);
    cout << close.to_string() << endl;
    cout << close.distance(n) << endl;


The file being called has the following within it:
1
2
3
4
1 1 A
2 2 B
3 3 C
4 4 D


My expected output should be:
1
2
B: (2, 2)
1.41421
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <string>
#include <map>
#include <cmath>
#include <stdexcept>
#include <algorithm>

struct node {

    double x, y ;

    double distance( const node& that ) const {

        const double dx = x - that.x ;
        const double dy = y - that.y ;
        return std::sqrt( dx*dx + dy*dy ) ;
    }

    // ...
};

const node& closest( const node& n, const std::map<std::string,node>& nodes ) {

    if( nodes.empty() ) throw std::invalid_argument( "empty map" ) ;

    const auto cmp = [&n] ( const auto& a, const auto& b ) // return true if a is closer to n
    { return n.distance(a.second) < n.distance(b.second) ; } ;

    // http://en.cppreference.com/w/cpp/algorithm/min_element
    return std::min_element( std::begin(nodes), std::end(nodes), cmp )->second ;
}

int main()
{
    std::map<std::string,node> map { { "a", { 1, 2 } },  { "b", { 2, 1 } },  { "c", { 2, 2 } } } ;

    node n { 1.6, 1.3 } ;
    const node& nearest = closest( n, map ) ;

    std::cout << '(' << nearest.x << ',' << nearest.y << ") at a distance of "
              << n.distance(nearest) << '\n' ;
}

http://coliru.stacked-crooked.com/a/79ebd4cad1122bc7
I am getting this error when I try and do what you have done:

1
2
error: could not convert 'std::min_element<std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, Node> >, Network::closest(Node&)::<lambda(const auto:1&, const auto:2&)> >(((Network*)this)->Network::nodes.std::map<_Key, _Tp, _Compare, _Alloc>::begin<std::basic_string<char>, Node, std::less<std::basic_string<char> >, std::allocator<std::pair<const std::basic_string<char>, Node> > >(), ((Network*)this)->Network::nodes.std::map<_Key, _Tp, _Compare, _Alloc>::end<std::basic_string<char>, Node, std::less<std::basic_string<char> >, std::allocator<std::pair<const std::basic_string<char>, Node> > >(), cmp)' from 'std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, Node> >' to 'Node'
     return std::min_element(nodes.begin(), nodes.end(), cmp);
Last edited on
Ideally, switch to a more current version of the compiler and compile with:
g++ -std=c++14 -Wall -Wextra -pedantic-errors ...

In the interim, modify the function to:
1
2
3
4
5
6
7
8
9
10
11
const node& closest( const node& n, const std::map<std::string,node>& nodes ) {

    if( nodes.empty() ) throw std::invalid_argument( "empty map" ) ;
    
    using kvpair = std::pair< const std::string, node > ; 
    const auto cmp = [&n] ( const kvpair& a, const kvpair& b ) 
    { return n.distance(a.second) < n.distance(b.second) ; } ;

    // http://en.cppreference.com/w/cpp/algorithm/min_element
    return std::min_element( std::begin(nodes), std::end(nodes), cmp )->second ;
}

http://coliru.stacked-crooked.com/a/bbc1ede7a5048d7e
1
2
// return std::min_element(nodes.begin(), nodes.end(), cmp);
return std::min_element(nodes.begin(), nodes.end(), cmp)->second;
Topic archived. No new replies allowed.