2017-01-09 3 views
0

Я прочитал почти все нити, которую я нашел через Google, но это не помогло мне ..Возврат индекс позиции STRUCT в векторе

У меня-структуру внутри класса:

struct animation { 
    int identifier; 
    int another_variable; 
}; 

хранить кучу этих структур в векторе:

static std::vector<animation> anims; 

Теперь мне нужно найти индекс (позицию) в виде структуры, на основании идентификатора поля.

// This is what I found so far 
int Animation::get_animation_index(int identifier) {   
    std::find(anims.begin(), anims.end(), identifier) - anims.begin(); 
} 

Идея заключается в том, чтобы получить вектор индекс anims [0] .. anims [хой], где структура с хм идентификатором хранится.

Я попробовал его в цикле, но тогда я только получить доступ к самому объекту, а не индекс ..

for (Animation::animation a : anims) { 
    if (a.identifier == identifier) { 
     // a is now the object, but I need the vector index.. 

Любые идеи?

+0

Используйте «старый стиль» для цикла. –

+0

'for (size_t i = 0; i David

+0

Посмотрите на http: // stackoverflow.com/questions/589985/vectors-structs-and-stdfind, например. или более актуальным http://stackoverflow.com/questions/14437825/using-stdfind-with-a-predicate –

ответ

7
for (Animation::animation const& a : anims) { // note: reference 
    if (a.identifier == identifier) { 
     return std::addressof(a) - std::addressof(anims[0]); 
    } 
} 

или:

std::find_if(anims.begin(), anims.end(), 
     [ident](const animation& a) { return a.identifier == ident; }) 
    - anims.begin(); 

или, если анимация не может присутствовать:

int find_index(int ident) 
{ 
    auto it = std::find_if(anims.begin(), anims.end(), 
       [ident](const animation& a) 
       { 
        return a.identifier == ident; 
       }); 
    if (it == anims.end()) 
     return -1; // or throw, depending on requirements 
    else 
     return it - anims.begin(); 
} 

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

int find_index_sorted(const std::vector<animation>& anims, int ident) 
{ 
    struct lower_ident 
    { 
     constexpr bool operator()(const animation& l, int r) const { 
      return l.identifier < r; 
     } 

     constexpr bool operator()(int l, const animation& r) const { 
      return l < r.identifier; 
     } 
    }; 
    constexpr auto pred = lower_ident(); 
    auto it = std::lower_bound(anims.begin(), anims.end(), ident, pred); 
    if (it == anims.end() or pred(ident, *it)) 
     return -1; 
    return it - anims.begin(); 
} 
+0

Почему это запрещено? – elasticman

+0

@elasticman понятия не имеет. Это правильный ответ :) –

+0

Спасибо, это сработало! – elasticman

1

Альтернатива @RichardHodges find_index который проще имо:

for (size_t i = 0; i < anims.size(); ++i) 
    if (anims[i].identifier == id) 
     return i; 
+0

Если производительность важна для вас, вы обнаружите, что компилятор будет более стремиться оптимизировать версии, основанные на итераторе. Повторный вызов 'anims.size()' в тесте цикла приведет к победе над попытками компилятора выполнить разворот цикла. Я понимаю, что разница небольшая для малых векторов. Для больших векторов это может быть фактором. По этой причине обычно лучше «лучше» использовать алгоритмы std. –

+0

@ RichardHodges Я был бы шокирован, если компиляторы не смогут оптимизировать это так же, как и версии, основанные на итераторе. Есть ли у вас какие-либо ссылки, подтверждающие это требование? Причина, по которой я был бы шокирован, заключается в том, что A) вектор не может быть изменен в цикле и B) примерно в течение десятилетия это был де-факто способ записи циклов, поэтому было бы чрезвычайно полезно, чтобы компиляторы оптимизировали этот конкретный кейс хорошо.Мне всегда говорили, что это «заданный», компилятор будет повторять этот вызов 'size()', и в подобных ситуациях – David

+0

подготовиться к тому, чтобы быть в шоке, как и я: https://godbolt.org/g/anVZIv Примечание. отсутствие разворота петли и дорогостоящий режим адресации с косвенным смещением в третьей функции. И на clang, и на gcc. –

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