2014-10-23 3 views
0

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

У меня есть коллекция указатель к элементам:

std::vector<Item*>* collection; 

Мне нужно применить выбор к элементам. Выбор осуществляется в несколько этапов, каждый закодированный внутри функции:

bool pass_step0(const Item& item); 

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

std::vector<int> nsurvivals_after_step; 
std::vector<bool> mask(collection->size(), true); 

int i = 0; 
for (item : *collection) { 
    if (not(pass_step0(*item)) { mask[i] = false; } 
    ++i; 
} 
nsurvivals.append(count(mask.begin(), mask.end(), true)); 

i = 0; 
for (item : *collection) { 
    if (not(pass_step1(*item)) { mask[i] = false; } 
    ++i; 
} 
nsurvivals.append(count(mask.begin(), mask.end(), true)); 

Есть много повторений в коде, и я должен использовать глобальный индекс i. Как использовать более сложную функцию C++ для ее улучшения?

+1

Я не вижу нигде в коде ' & = '. Какова ваша фактическая цель, чего вы пытаетесь выполнить с помощью '& =' или кода, который вы предоставили? –

ответ

1

Это немного лучше:

std::vector<int> nsurvivals_after_step; 
std::vector<bool> mask(collection->size(), true); 

std::transform(collection->begin(), collection->end(), mask.begin(), mask.begin(), 
       [](Item* i, bool m) { return m and pass_step0(*i); } 
nsurvivals.append(count(mask.begin(), mask.end(), true)); 

std::transform(collection->begin(), collection->end(), mask.begin(), mask.begin(), 
       [](Item* i, bool m) { return m and pass_step1(*i); } 
nsurvivals.append(count(mask.begin(), mask.end(), true)); 

это нормально так, как я использую std::transform? третий и четвертый аргументы одинаковы!

+0

Если вы собираетесь использовать 'std :: transform', вам нужна версия' UnaryOperation' ... как есть, ваш двоичный op выполняет 'm && pass_step0', но' m' всегда будет 'true 'так как это вы его инициализировали. Это просто дополнительный код. Также не используйте 'and', используйте' && '. – Barry

+0

Нет, 'm' всегда истинно только для первого' transform'. Почему я не должен использовать 'и'? –

1

Вы просто хотите подсчитать количество элементов, которые он собирает, проходя мимо фильтров? Вы можете проверить подталкивание-х range adaptors:

using namespace boost::adaptors; 

const Item& to_ref(const Item* item) { return *item; } 

nsurvivals.push_back(size(*collection 
          | transformed(to_ref) 
          | filtered(pass_step0))); 
nsurvivals.push_back(size(*collection 
          | transformed(to_ref) 
          | filtered(pass_step1))); 

Это, вероятно, как чистая, как он получает. Кроме того, если вы хотите, чтобы пройти несколько шагов, вы можете просто держать трубы происходит:

int passBoth = size(*collection 
        | transformed(to_ref) 
        | filtered(pass_step0) 
        | filtered(pass_step1)); 

[Update] Перевал * функции, очевидно, взять ссылки, поэтому добавили transformed

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