How to print repeated elements of a std :: list in C ++ without using loops?

1

How do I print all the elements of a list (std :: list) of pairs in c ++, containing max_elemnt repeated ?

list<pair<int, int>> l;
l.push_back ( std::make_pair ( 1, 90 ) );
l.push_back ( std::make_pair ( 2, 90 ) );
l.push_back ( std::make_pair ( 3, 75 ) );
l.push_back ( std::make_pair ( 4, 40 ) );
l.push_back ( std::make_pair ( 5, 90 ) );

I mean ... if I have that list above, how do I make the output:

  

Student 1: 90.
  Student 2: 90.
  Student 5: 90.

... Showing not only the largest element, but the largest element and all the repeated ones. I do not know if I express myself well.

I understand that max_element only returns the first item in the list. If I have a list with the elements {3,7,9,5,6,4,9} , and as we can see there are two repeated , if I do something like:

int myints[] = {3,7,9,5,6,4,9};
std::cout << *std::max_element(myints,myints+7) << '\n';

The exit would be:

  

9

I need the output to be all the repeated numbers, that is, there are 2, so it prints all the repeated major numbers, but using the pair that we see in the first example.

Is there any utility that shows all the repeats?

    
asked by vangodp 02.09.2016 в 15:02
source

2 answers

2

One way, that if you put in a .h, it could be "the utility":)

inline
void mostrarMayores(std::list<std::pair<int,int>> l)
// recibe una copia para no modificar la lista original
{
    auto comp = [](const std::pair<int,int>& a, const std::pair<int,int>& b) {
        return a.second > b.second;
    };

    auto as_str = [](const std::pair<int, int>& p) {
        std::ostringstream ss;
        ss << "Alumno " << p.first << ": " << p.second;
        return ss.str();
    };

    l.sort(comp);

    std::transform(l.begin(), std::upper_bound(l.begin(), l.end(), *l.begin(), comp),
                   std::ostream_iterator< std::string >( std::cout, "\n" ),
                   as_str);
}
    
answered by 03.09.2016 / 05:35
source
-1

I do not know of any utility that does directly show all the repeated ones.

But it is possible to do it without loops. Using recursion.

First we will get the maximum with a dameMax function.

#include <cstdlib>
#include <list>
#include<stdexcept>
#include<iostream>
using namespace std;

int dameMaxRecursivo( int max, std::list<pair<int, int>>::const_iterator it,
                      std::list<pair<int,int>>::const_iterator end )
{
    if ( it==end )
        return max;
    if ( it->second>max )
        return dameMaxRecursivo( it->second, ++it, end );
    else
        return dameMaxRecursivo( max, ++it, end );
}

int dameMax( const std::list<pair<int, int>>& lista )
{
    if ( lista.size()==0 )
        throw invalid_argument("dameMax requiere una lista no vacia.");
    auto it = lista.begin();
    int max = it->second;
    ++it;
    return dameMaxRecursivo( max, it, lista.end() );
}

dameMax checks that the list is not empty and calls the recursive function by passing the maximum until now (the value of the first element in the list) and an iterator to the next element. It also passes iterator at the end so that the recursive function knows when to stop.

First the recursive function checks if it has reached the end. If you do not compare the maximum so far with the element in the received iterator. If it is greater it calls itself with this new value that is greater and with the iterator pointing to the next element, if it is not greater it calls itself with the maximum until now and also with the iterator pointing to the next element.

To print without loops we use the same technique:

void mostarMayoresRecursivo( int max, std::list<pair<int, 
                             int>>::const_iterator it,
                             std::list<pair<int,int>>::const_iterator end)
{
    if ( it==end ) 
        return;
    if ( it->second == max )
      std::cout<<"Alumno " << it->first << ":" << it->second << std::endl;
    mostarMayoresRecursivo( max, ++it, end );
}

void mostrarMayores( const std::list<pair<int, int>>& lista )
{
    if ( lista.size()==0 )
        return;
    int max = dameMax( lista );
    mostarMayoresRecursivo( max, lista.begin(), lista.end() );
}

A seasoned reader will notice that there are still loops. It is quite possible that the < < for streams is implemented with some loop. Of course this is also possible to implement without loops using the same technique.
The recursion used, which is tail recursion, can be optimized by some compilers to a loop. But it is also possible to force the compiler not to do it.
And it is possible that system calls to print on screen use a buffer mechanism and end up printing in a loop even though you pass the characters to them one by one without loops. But this is already something external to your program.

That this can be done does not mean that it is advisable. There are cases in which it is recommended, it is a common technique in functional programming.

    
answered by 19.02.2017 в 11:22