Сортировка станд.:: карта значением, прежде чем произведено и уничтожает

К chroot каталог SFTP Вы должны

  1. , Создают пользователя и вынуждают корень быть владельцем его

    cd /home
    mkdir john
    useradd -d /home/john -M -N -g users john
    sudo chown root:root /home/john
    sudo chmod 755 /home/john
    
  2. , Изменяют местоположение подсистемы на/etc/ssh/sshd_config:

    #Subsystem sftp /usr/lib/openssh/sftp-server
    Subsystem sftp internal-sftp
    

    и создают пользовательский раздел в конце файла (ssh, может умереть, повторно меча икру, если помещено после строки Подсистемы):

    Match User john
        ChrootDirectory /home/john
        ForceCommand internal-sftp
        AllowTCPForwarding no
        X11Forwarding no
    
10
задан Rene Knop 23 October 2018 в 18:22
поделиться

5 ответов

Карты хранятся в виде дерева, отсортированного в порядке ключей. Вам нужны 10 наименьших (или наибольших) целочисленных значений и их ключи, верно?

В этом случае выполните итерацию карты и поместите все пары ключ-значение в вектор пар ( std :: vector < std :: pair >) . Я думаю, вы можете просто использовать для этого конструктор two-iterator-arg std :: vector. Затем используйте std :: partial_sort для вектора. Укажите компаратор для partial_sort, который сравнивает пары, просто сравнивая значение int, игнорируя строку ключа. Затем у вас есть 10 пар, которые вам нужны в начале вектора, а остальная часть вектора содержит оставшиеся пары в неопределенном порядке.

Код (непроверенный):

typedef std::pair<std::string, int> mypair;

struct IntCmp {
    bool operator()(const mypair &lhs, const mypair &rhs) {
        return lhs.second < rhs.second;
    }
};


void print10(const std::map<std::string,int> &mymap) {
    std::vector<mypair> myvec(mymap.begin(), mymap.end());
    assert(myvec.size() >= 10);
    std::partial_sort(myvec.begin(), myvec.begin() + 10, myvec.end(), IntCmp());

    for (int i = 0; i < 10; ++i) {
        std::cout << i << ": " << myvec[i].first 
            << "-> " << myvec[i].second << "\n";
    }
}

Обратите внимание, что если есть несколько строк с одинаковым значением по обе стороны от предела 10, то не указывается, какие из них вы получите. Вы можете контролировать это, если ваш компаратор тоже будет смотреть на строку в случаях, когда целые числа равны.

25
ответ дан 3 December 2019 в 14:18
поделиться

Для итерации по значению вы можете использовать boost :: multi_index . Это будет выглядеть следующим образом:

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
using namespace boost::multi_index;

struct X {
  X( std::string val_str, int val_int ) : val_str(val_str), val_int(val_int) {};
  std::string val_str;
  int         val_int;
};

typedef multi_index_container<
    X,
    indexed_by<
        hashed_unique< member<X, std::string, &X::val_str> >,
        ordered_non_unique< member<X, int, &X::val_int> >
    >
> X_map;

void func()
{
   X_map data;
   data.insert( X("test", 1) );
   // ...

   // search by val_str 
   // complexity is equal to O(1) for hashed index (worst cast O(n) ), 
   // and O(log n) for ordered index
   X_map::const_iterator it = data.find( "test" );
   // ...

   // iterate in order of val_int
   size_t N = 0;
   for ( X_map::nth_index<1>::type::const_iterator it = data.get<1>().begin(); N < 10 && it != data.get<1>().end(); ++it, ++N ) {
     // copy elements somewhere
   }
}

Вы можете использовать любой индекс для итерации ( val_str или val_int ).

.
7
ответ дан 3 December 2019 в 14:18
поделиться

Возможно, это не самый элегантный способ, но вы можете отсортировать их по значению в наборе как:

#include <map>
#include <set>
#include <iostream>
#include <string>

using namespace std;

struct sortPairSecond
{
   bool operator()(const pair<string, int> &lhs, const pair<string, int> &rhs)
   {
       return lhs.second < rhs.second;
   }
};


int main (int argc, char *argv[])
{
    cout << "Started...\n";
    map<string, int> myMap;
    myMap["One"]   = 1;
    myMap["Ten"]   = 10;
    myMap["Five"]  = 5;
    myMap["Zero"]  = 0;
    myMap["Eight"] = 8;


    cout << "Map Order:\n---------------\n";
    set<pair<string,int>, sortPairSecond > mySet;
    for(map<string, int>::const_iterator it = myMap.begin(); it != myMap.end(); ++it)
    {
        cout << it->first << " = " << it->second << "\n";
        mySet.insert(*it);
    }

    cout << "\nSet Order:\n--------------\n";
    for(set<pair<string, int> >::const_iterator it = mySet.begin(); it != mySet.end(); ++it)
    {
        cout << it->first << " = " << it->second << "\n";
    }

    return 1;
}


1
ответ дан 3 December 2019 в 14:18
поделиться

Другая возможность - построить обратную карту. Для вас это будет std :: map . Записи на обратной карте отсортированы по их значению.

В моем ящике с инструментами для таких случаев есть следующее:

template< typename TK, typename TV, class TP, class TA, typename T1, typename T2 >
inline void asserted_insert(std::map<TK,TV,TP,TA>& m, const T1& k, const T2& v)
{
  typedef std::map<TK,TV,TP,TA>                   map_type;
  typedef typename map_type::value_type           value_type;
  assert( m.insert(value_type(k,v)).second );
}

template< class TMap > struct reverse_map;
template< typename T1, typename T2 > struct reverse_map< std::map<T1,T2> > {
  typedef std::map<T2,T1>                         result_t;
};

template< typename T1, typename T2, class TP1, class TA1, class TP2, class TA2 >
inline void build_reverse_map(const std::map<T1,T2,TP1,TA1>& map, std::map<T2,T1,TP2,TA2>& reverse_map)
{
  typedef std::map<T1,T2,TP1,TA1>                 map_type;

  for( typename map_type::const_iterator it=map.begin(),
                                        end=map.end(); it!=end; ++it ) {
    asserted_insert( reverse_map, it->second, it->first );
  }
}

Этот код предполагает, что значения тоже уникальны (и выдает утверждение, если это не так). Если это не относится к вашей проблеме, вы можете легко изменить код для использования мульти-карты.

1
ответ дан 3 December 2019 в 14:18
поделиться

Если вы выполняете итерацию с использованием итератора карты, вы получите элементы, отсортированные по ключу, поскольку он внутренне использует сбалансированное двоичное дерево для хранения значений. Таким образом, вы можете просто извлечь из него 10 значений с помощью итераторов. Вы этого хотите или хотите заняться чем-то другим? Пожалуйста, поясните.

РЕДАКТИРОВАТЬ: Вместо использования вектора и сортировки вы можете напрямую использовать функцию set и передать функцию сравнения. Затем вы можете извлечь 10 лучших элементов. Это мой тестовый код:

typedef std::pair<std::string, int> MyPair;


struct MyTestCompare
{

    bool operator()(const MyPair& firstPair, const MyPair& secondPair) const
    {
        return firstPair.second < secondPair.second;
    }
};

int main()
{
    std::map<std::string, int> m;
    m[std::string("1")] = 10;   
m[std::string("2")] = 40;
m[std::string("3")] = 30;
m[std::string("4")] = 20;



    std::set<MyPair,MyTestCompare> s;
    std::map<std::string, int>::iterator iter = m.begin();
    std::map<std::string, int>::iterator endIter = m.end();
    for(; iter != endIter; ++iter)
    {
        s.insert(*iter);
    }

}
1
ответ дан 3 December 2019 в 14:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: