2016-06-01 9 views
5

Mam tablicę w stylu C o nazwie board, która zawiera niektóre z nich: char. Próbuję utworzyć std::array lub std::vector (albo byłoby w porządku, chociaż najlepiej byłoby użyć std::array) do przechowywania wszystkich indeksów board, które są pewną wartością (w moim przypadku, 0).
Kod ten napisałem jest funkcjonalny i dobrze działa:Funkcja biblioteki standardowej w celu utworzenia tablicy indeksów, której odpowiadająca wartość to podana liczba.

std::vector<int> zeroes; 
zeroes.reserve(16); 
//board has 16 elements, so zeroes.size() will never be larger than 16. 
//I used this reserve for speedup - the compiler doesn't require it. 
for (int i = 0; i < 16; ++i) 
{ 
    if (board[i] == 0) 
    { 
     zeroes.push_back(i); 
    } 
} 

Jednak z dotychczasowych doświadczeń, ilekroć std funkcja istnieje, który może zastąpić część mojego kodu, to terser i stąd stylistycznie preferowane i również szybciej. Moja funkcja wydaje się dość prostą operacją - wiem, że istnieje standardowa funkcja *, która umożliwia dostęp do indeksu tablicy zawierającej wartość, gdy ta wartość występuje tylko raz ** w tablicy. Czy istnieje standardowa funkcja tworzenia tablicy indeksów zawierających wartość, zakładając, że istnieje więcej niż jeden taki indeks?


* Technicznie dwie zagnieżdżone wywołania funkcji: int x = std::distance(board, std::find(board, board + 16, 0));. Zobacz the accepted answer here.
** Cóż, nadal działa, jeśli obecny jest więcej niż jeden indeks o pożądanej wartości, ale zwraca tylko pierwszy taki indeks, co nie jest zbyt użyteczne w moim kontekście.


Edit: Jako jedną z odpowiedzi na pytanie źle, będę wyjaśnić, co ja szukam. Powiedzmy, że mamy:

char board[16] = {0, 2, 0, 4, 
        2, 4, 8, 2, 
        0, 0, 8, 4, 
        2, 0, 0, 2}; 

Teraz indeksy których szukam są {0, 2, 8, 9, 13, 14} ponieważ board[0] = 0, board[2] = 0, board[8] = 0, itd. I są to tylko liczby, które spełniają tej nieruchomości.

+0

Boost.ranges może to zrobić. –

+0

Miałem na myśli 'boost :: filter_iterator' –

+0

Ten kod wygląda dobrze, z wyjątkiem początkowego wywołania" zeroes.reserve (16) ". Wywołania 'push_back' dopasują rozmiar' zeroes' w razie potrzeby, a gdy skończy się, 'zeroes.size()' wskaże liczbę indeksów. –

Odpowiedz

6

Oto rozwiązanie przy użyciu std::iota i std::remove_if:

#include <algorithm> 
#include <iostream> 

int main() { 
    const std::size_t board_size = 16; 
    char board [board_size] = { 
    0, 2, 0, 4, 
    2, 4, 8, 2, 
    0, 0, 8, 4, 
    2, 0, 0, 2 
    }; 

    // Initialize a zero-filled vector of the appropriate size. 
    std::vector<int> zeroes(board_size); 

    // Fill the vector with index values (0 through board_size - 1). 
    std::iota(zeroes.begin(), zeroes.end(), 0); 

    // Remove the index values that do not correspond to zero elements in the board. 
    zeroes.erase(std::remove_if(zeroes.begin(), zeroes.end(), [&board] (int i) { 
    return board[i] != 0; 
    }), zeroes.end()); 

    // Output the resulting contents of the vector. 
    for (int i : zeroes) { 
    std::cout << i << std::endl; 
    } 
} 

Wyjście z programu (demo):

0 
2 
8 
9 
13 
14 
+1

dobry ruch za pomocą jota zamiast generowania samych wskaźników –

Powiązane problemy