Como colocar um determinado elemento em uma lista, dada a posição?

92

Então, eu tenho uma lista:

list<Object> myList;
myList.push_back(Object myObject);

Não tenho certeza, mas estou certo de que este seria o elemento "0" na matriz. Posso usar alguma função que retorne "myObject"?

Object copy = myList.find_element(0);

?

Teste
fonte
8
Não há matriz - é uma lista. Se você deseja indexar por inteiro, por que não usa vector?
Paul J. Lucas de
2
Se você sempre quiser o elemento 0, use front().
Paul J. Lucas de
Não testei, mas presumo que myList.front () + num funcionaria aqui
Serguei Fedorov
2
@SergueiFedorov: não, não faz
Algoman

Respostas:

129

Se você freqüentemente precisa acessar o enésimo elemento de uma sequência, std::listque é implementado como uma lista duplamente vinculada, provavelmente não é a escolha certa. std::vectorou std::dequeprovavelmente seria melhor.

Dito isso, você pode obter um iterador para o enésimo elemento usando std::advance:

std::list<Object> l;
// add elements to list 'l'...

unsigned N = /* index of the element you want to retrieve */;
if (l.size() > N)
{
    std::list<Object>::iterator it = l.begin();
    std::advance(it, N);
    // 'it' points to the element at index 'N'
}

Para um contêiner que não fornece acesso aleatório, como std::list, std::advancechamadas operator++nos Ntempos do iterador . Alternativamente, se sua implementação de biblioteca padrão fornecer, você pode chamar std::next:

if (l.size() > N)
{
    std::list<Object>::iterator it = std::next(l.begin(), N);
}

std::nexté efetivamente encapsula uma chamada para std::advance, tornando mais fácil avançar os Ntempos de um iterador com menos linhas de código e menos variáveis ​​mutáveis. std::nextfoi adicionado em C ++ 11.

James McNellis
fonte
18
Enquanto você paga uma penalidade de desempenho ao pesquisar uma lista vinculada devido à falta de acesso aleatório, você paga uma penalidade de desempenho muito maior se precisar inserir ou remover dados no meio de um vetor ou deque. A questão não contém realmente informações suficientes para decidir se eles estão usando o contêiner ideal para seus propósitos.
próximo de
1
É importante notar que ao usar std::advanceou std::next, é fácil invocar o UB. Não há verificação de limites.
okovko
33

std::listnão fornece nenhuma função para obter o elemento dado um índice. Você pode tentar obtê-lo escrevendo algum código, o que eu não recomendaria, porque seria ineficiente se você precisar fazer isso com frequência.

O que você precisa é: std::vector. Use-o como:

std::vector<Object> objects;
objects.push_back(myObject);

Object const & x = objects[0];    //index isn't checked
Object const & y = objects.at(0); //index is checked 
Nawaz
fonte
7
std::list<Object> l; 
std::list<Object>::iterator ptr;
int i;

for( i = 0 , ptr = l.begin() ; i < N && ptr != l.end() ; i++ , ptr++ );

if( ptr == l.end() ) {
    // list too short  
} else {
    // 'ptr' points to N-th element of list
}
furas
fonte
3

Talvez não seja a maneira mais eficiente. Mas você pode converter a lista em um vetor.

#include <list>
#include <vector>

list<Object> myList;

vector<Object> myVector(myList.begin(), myList.end());

Em seguida, acesse o vetor usando o operador [x].

auto x = MyVector[0];

Você poderia colocar isso em uma função auxiliar:

#include <memory>
#include <vector>
#include <list>

template<class T>
shared_ptr<vector<T>> 
ListToVector(list<T> List) {
shared_ptr<vector<T>> Vector {
        new vector<string>(List.begin(), List.end()) }
return Vector;
}

Em seguida, use a função auxiliar desta forma:

auto MyVector = ListToVector(Object);
auto x = MyVector[0];
Bill Moore
fonte