2016-06-01 11 views
5

Ho un array in stile C chiamato board che contiene alcuni char. Sto cercando di creare un std::array o std::vector (o andrebbe bene, anche se std::array sarebbe preferibile) per memorizzare tutti gli indici di board che sono un certo valore (nel mio caso, 0).
Questo codice che ho scritto è funzionale e funziona bene:Funzione di libreria standard per creare una serie di indici il cui valore corrispondente è un numero dato

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); 
    } 
} 

Tuttavia, dall'esperienza passata, ogni volta che una funzione std esiste che potrebbe sostituire parte del mio codice, è terser e quindi stilisticamente preferito e anche più veloce. La mia funzione sembra un'operazione abbastanza basilare: so che esiste una funzione standard * per accedere all'indice di un array che contiene un valore quando quel valore si verifica solo una volta ** nell'array. Quindi, esiste una funzione standard per creare una matrice degli indici che contengono un valore, supponendo che esista più di uno di questi indici?


* Tecnicamente, due chiamate di funzioni annidate: int x = std::distance(board, std::find(board, board + 16, 0));. Vedi the accepted answer here.
** Bene, funziona ancora se è presente più di un indice con il valore desiderato, ma restituisce solo il primo indice, che non è molto utile nel mio contesto.


Edit: Come una delle risposte capito la domanda, ti chiarire quello che sto cercando. Diciamo che abbiamo:

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

Ora, gli indici che sto cercando sono {0, 2, 8, 9, 13, 14} perché board[0] = 0, board[2] = 0, board[8] = 0, ecc e questi sono gli unici numeri che soddisfano quella proprietà.

+0

Boost.ranges possono farlo. –

+0

Stavo pensando 'boost :: filter_iterator' –

+0

Quel codice sembra a posto, tranne per la chiamata iniziale a' zeroes.reserve (16) '. Le chiamate a 'push_back' regoleranno la dimensione di' zeroes 'quando necessario, e quando sarà finita, 'zeroes.size()' ti dirà quanti indici ci sono. –

risposta

6

Ecco una soluzione che utilizza std::iota e 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; 
    } 
} 

output del programma (demo):

0 
2 
8 
9 
13 
14 
+1

buona mossa usando iota invece di generare autonomamente le informazioni –

Problemi correlati