2017-01-28 12 views
0

У меня есть контейнер, и я бы хотел выбрать итератор, который бы случайно использовал предикат. Если это помогает быть конкретным, контейнер представляет собой карту.Получите итератор из контейнера равномерно случайным от итераторов, которые удовлетворяют предикату

наивности, я бы сказал так:

std::count_if, чтобы получить число элементов в диапазоне.

Выберите случайное число btwn 0 и num_elements-1.

Создайте лямбду, чтобы создать предикат с состоянием, который подсчитывает до случайного числа и возвращает только true.

std::find_if с лямбда.

Будет ли это работать, и есть ли лучший способ? В качестве альтернативы, я мог бы использовать count вместо count_if и регенерировать число, если он прервал предикат. Может быть полезно, если предикат в основном верен, я полагаю, но не буду работать хорошо для моих целей.

+0

Не могли бы вы пояснить «итератор, который удовлетворяет случайному сказуемому»? Итератор над контейнером? Каковы аргументы (ы) для предиката? Что вы подразумеваете под итератором, который удовлетворяет предикату? – qxz

+0

Я предполагаю, что у вас достаточно идеи для разработки кода. –

+0

Отредактированное название и спасибо за редактирование вопроса. Ответ собеседника выглядит так, как я думал. –

ответ

1

Вы можете обменять память на производительность, сохраняя все итераторы, для которых предикат является истинным в отдельном контейнере, а затем используйте случайное число, чтобы выбрать из него итератор. Таким образом, вам нужно перебирать последовательность только один раз (обратите внимание, однако, что вам по-прежнему нужен итератор вперед, поскольку сохраненные итераторы ввода будут недействительными, как только вы перейдете к следующему элементу). Например:

template<typename ForwardIterator, typename Predicate> 
    ForwardIterator random_iterator(ForwardIterator first, 
            ForwardIterator last, 
            Predicate pred) 
{ 
    // store iterators to elements where the predicate is true 
    std::deque<ForwardIterator> store; 
    for (; first != last; ++first) 
    if pred(*first) 
     store.push_back(first); 

    // if no element satisfies the predicate, return last 
    if (store.size() == 0) 
    return last; 

    // get a random number in range [0, store.size()) 
    int rand = get_random_number(store.size()); 

    // return the corresponding iterator 
    return store[rand]; 
} 
+0

Да, это выглядит правильно. Спасибо за шаблон; похоже, что я мог бы сыграть с этим и получить интересный итератор от этого тоже. –

 Смежные вопросы

  • Нет связанных вопросов^_^