как отсортировать элементы по одной мере - PullRequest
3 голосов
/ 22 июля 2011

В C ++ я не совсем понимаю, как сортировать элементы, определяя пользовательскую функцию.

Cppreference.com говорит, что для функции сравнения:

comp - функция сравнения, которая возвращает true, если первый аргумент меньше второго.

bool cmp (const Type1 & a, const Type2 & b);

Естественно, я бы подумал, что для сортировки элементов мне нужно определить меру, а функция сортировки отсортирует их в зависимости от меры.

В моем примере я хотел бы отсортировать файлы изображений в зависимости от того, как далеко они находятся от камеры. У меня есть вектор boost :: filesystem :: path, ссылающийся на каталоги последовательностей изображений

vector<boost::filesystem::path> path_vec

и я, естественно, подумал бы, что мне нужно написать такую ​​функцию, как

double z_distance( boost::filesystem::path filename, integer time )

что вернет double для всех элементов и отсортирует их в порядке возрастания или убывания для каждого кадра (таким образом, изменяя время в аргументе).

Подскажите, как мне превратить эту функцию, которая возвращает одно значение, в функцию bool, необходимую для функции сортировки?

И как я могу передать аргументы , если я могу только передать имя функции, а не полный вызов функции?

Ответы [ 4 ]

3 голосов
/ 22 июля 2011

Когда вы определяете

 bool nearer(const boost::filesystem::path& a, const boost::filesystem::path& b)
 {
   int somevalue = 0;
   return z_distance(a, somevalue) < z_distance(b, somevalue);
 }

, вы можете сделать

 std::sort(path_vec.begin(), path_vec.end(), nearer);

Однако я не знаю, что делать со вторым аргументом вашей функции z_distance().Может быть, вы можете получить его из своих файлов или использовать функцию сравнения вместо функции.Функтор см. В ответе @templatetypedef.

Поскольку вы пометили VC ++ 10, вы также можете использовать функцию C ++ 0x: написать лямбда-выражение (функцию adhoc) для передачи аргументов:

 int somevalue = 0;
 std::sort(path_vec.begin(), path_vec.end(), 
   [=](const boost::filesystem::path& a, const boost::filesystem::path& b) -> bool
   {
     return z_distance(a, somevalue) < z_distance(b, somevalue);
   }
 );
2 голосов
/ 22 июля 2011

Перегрузите operator<, чтобы вернуть & A <& B, и сортировка должна работать только с begin (), end () и ничего больше. </p>

Так что

 bool operator<(const SomeType& a, const SomeType& b)
 {
   return z_distance(a, 0) < z_distance(b, 0);
 }

И вы должныбыть в состоянии назвать это так.

 std::vector<SomeType> vec;
 std::sort(vec.begin(), vec.end());
2 голосов
/ 22 июля 2011

Есть много способов сделать это.

Если вы случайно знаете, что второй аргумент z_distance всегда будет фиксированным значением, вы можете преобразовать функцию в компараторнаписав вспомогательную функцию, которая фактически выполняет сравнение.Например:

bool CompareByDistance(const boost::filesystem::path& lhs,
                       const boost::filesystem::path& rhs) {
    return z_distance(lhs, kSecondArg) < z_distance(rhs, kSecondArg);
}

Если вы не знаете, каким должен быть второй параметр функции z_distance, или его можно определить только во время выполнения, тогда вам может потребоватьсяиспользовать функциональный объект .Функциональный объект (иногда называемый функтором ) - это объект, который имитирует обычную функцию.Вы можете вызвать его, передав некоторое количество параметров, но, поскольку это объект, функция, вызываемая в результате вызова, может получить доступ к локальному состоянию в дополнение к параметрам.Один такой функциональный объект, который вы можете создать, может выглядеть так:

class CompareByDistance {
public:
    /* Constructor takes in the time that you want to sort at,
     * then stores it for later.
     */
    CompareByDistance(int time) : mTime(time) {

    }

    /* This is the function call operator that is called when you try
     * treating a CompareByDistance object as a function.  Note how it
     * uses the mTime field as a parameter to `z_distance`.
     */
    bool operator()(const boost::filesystem::path& lhs,
                    const boost::filesystem::path& rhs) const {
        return z_distance(lhs, mTime) < z_distance(rhs, mTime);
    }
private:
    const int mTime; // Store mTime for later
};

Теперь, если вы хотите отсортировать все в какой-то момент времени t, вы можете написать

sort(elems.begin(), elems.end(), CompareByDistance(t));

Для получения дополнительной информации офункторы и, как бесстыдный плагин, вот глава о функторах , которую я написал для курса C ++, который я преподавал год назад.

Надеюсь, это поможет!

1 голос
/ 22 июля 2011

Хорошо, вот где вы запутались ...

Функция сравнивает два элемента за раз, перенастраивая внутренний контейнер (дерево или что-то еще), основываясь на результате.Таким образом, все, что C ++ нужно знать в функциях STL, это элемент A, меньший, чем элемент B, основанный на вашей функции.

Итак, для всех вас волнует, что ваша функция сравнения может сравнивать их расстояния, имена людей илиКакого черта ты хочешь.Функция просто должна возвращать true, если один элемент меньше другого, и C ++ будет обрабатывать, как с ним сортироваться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...