c++ como - ¿Cómo utilizar el bucle for()basado en rango con std::map?




infinito programas (5)

El ejemplo común para C ++ 11 basado en rango para () bucles es siempre algo simple como esto:

std::vector<int> numbers = { 1, 2, 3, 4, 5, 6, 7 };
for ( auto xyz : numbers )
{
     std::cout << xyz << std::endl;
}

En cuyo caso xyz es un int . Pero, ¿qué pasa cuando tenemos algo como un mapa? ¿Cuál es el tipo de la variable en este ejemplo:

std::map< foo, bar > testing = { /*...blah...*/ };
for ( auto abc : testing )
{
    std::cout << abc << std::endl;         // ? should this give a foo? a bar?
    std::cout << abc->first << std::endl;  // ? or is abc an iterator?
}

Cuando el contenedor que se recorre es algo simple, parece que los bucles basados ​​en rango para () nos darán cada elemento, no un iterador. Lo que es bueno ... si fuera iterador, lo primero que siempre tendríamos que hacer es desreferenciarlo de todos modos.

Pero estoy confundido en cuanto a qué esperar cuando se trata de cosas como mapas y multimapas.

(Todavía estoy en g ++ 4.4, mientras que los bucles basados ​​en rangos están en g ++ 4.6+, así que aún no he tenido la oportunidad de probarlo).


Answers

Si el operador de asignación de copia de foo y bar es barato (por ejemplo, int, char, puntero, etc.), puede hacer lo siguiente:

foo f; bar b;
BOOST_FOREACH(boost::tie(f,b),testing)
{
  cout << "Foo is " << f << " Bar is " << b;
}

EDIT : El siguiente no funciona como antes : tiene que ser una declaración , no una expresión de valor l .

foo f;bar b;
for(std::tie(f,b) : testing)
{
   cout << "Foo is " << f << " Bar is " << b;
}

En C ++ 17 esto se denomina enlaces estructurados , lo que permite lo siguiente:

std::map< foo, bar > testing = { /*...blah...*/ };
for ( const auto& [ k, v ] : testing )
{
  std::cout << k << "=" << v << "\n";
}


De este documento: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2049.pdf

for( type-specifier-seq simple-declarator : expression ) statement

es sintácticamente equivalente a

{
    typedef decltype(expression) C;
    auto&& rng(expression);
    for (auto begin(std::For<C>::begin(rng)), end(std::For<C>::end(rng)); begin != end; ++ begin) {
        type-specifier-seq simple-declarator(*begin);
        statement
    }
}

Entonces, puedes ver claramente que lo que es abc en tu caso será std::pair<key_type, value_type > . Así que para imprimir puedes acceder a cada elemento por abc.first y abc.second


He fusionado las soluciones de user157196 y Carter Page:

class MapUtil {

    public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue( Map<K, V> map ){
        ValueComparator<K,V> bvc =  new ValueComparator<K,V>(map);
        TreeMap<K,V> sorted_map = new TreeMap<K,V>(bvc);
        sorted_map.putAll(map);
        return sorted_map;
    }

}

class ValueComparator<K, V extends Comparable<? super V>> implements Comparator<K> {

    Map<K, V> base;
    public ValueComparator(Map<K, V> base) {
        this.base = base;
    }

    public int compare(K a, K b) {
        int result = (base.get(a).compareTo(base.get(b)));
        if (result == 0) result=1;
        // returning 0 would merge keys
        return result;
    }
}




c++ c++11 for-loop dictionary