¿Cómo conseguir un determinado elemento en una lista, dada la posición?

92

Entonces tengo una lista:

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

No estoy seguro, pero estoy seguro de que este sería el elemento "0" de la matriz. ¿Hay alguna función que pueda usar que devuelva "myObject"?

Object copy = myList.find_element(0);

?

Prueba
fuente
8
No hay matriz, es una lista. Si desea indexar por entero, ¿por qué no lo usa vectoren su lugar?
Paul J. Lucas
2
Si siempre desea el elemento 0, use front().
Paul J. Lucas
No he probado esto, pero supongo que myList.front () + num funcionaría aquí
Serguei Fedorov
2
@SergueiFedorov: no, no es así
Algoman

Respuestas:

129

Si necesita acceder con frecuencia al enésimo elemento de una secuencia, std::listque se implementa como una lista doblemente enlazada, probablemente no sea la opción correcta. std::vectoro std::dequeprobablemente sería mejor.

Dicho esto, puede obtener un iterador para el elemento N 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 un contenedor que no proporciona acceso aleatorio, como std::list, std::advancellamadas operator++en el iterador Nveces. Alternativamente, si la implementación de su biblioteca estándar lo proporciona, puede llamar a std::next:

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

std::nextes efectivamente envuelve una llamada a std::advance, lo que facilita el avance de los Ntiempos de un iterador con menos líneas de código y menos variables mutables. std::nextse agregó en C ++ 11.

James McNellis
fuente
18
Si bien paga una penalización de rendimiento al buscar una lista vinculada debido a la falta de acceso aleatorio, paga una penalización de rendimiento mucho mayor si necesita insertar o eliminar datos en medio de un vector o deque. La pregunta en realidad no contiene suficiente información para decidir si están usando el contenedor ideal para sus propósitos.
tloach
1
Vale la pena señalar que cuando se usa std::advanceo std::next, es fácil invocar UB. No hay verificación de límites.
okovko
33

std::listno proporciona ninguna función para obtener un elemento dado un índice. Puede intentar obtenerlo escribiendo algún código, que no recomendaría, porque sería ineficaz si lo necesitara con frecuencia.

Lo que necesita es: std::vector. Úselo 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
fuente
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
fuente
3

Quizás no sea la forma más eficiente. Pero podrías convertir la lista en un vector.

#include <list>
#include <vector>

list<Object> myList;

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

Luego acceda al vector usando el operador [x].

auto x = MyVector[0];

Podrías poner eso en una función 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;
}

Luego use la función de ayuda de esta manera:

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