Pozisyona göre bir listede belirli bir öğe nasıl alınır?


95

Bu yüzden bir listem var:

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

Emin değilim ama bunun dizideki "0." eleman olacağından eminim. Kullanabileceğim, "myObject" i döndürecek herhangi bir işlev var mı?

Object copy = myList.find_element(0);

?


8
Dizi yok - bu bir liste. Tamsayıya göre indekslemek istiyorsanız, vectorbunun yerine neden kullanmıyorsunuz ?
Paul J. Lucas

2
Her zaman 0 öğesini istiyorsanız, kullanın front().
Paul J. Lucas

Bunu test etmedim, ancak myList.front () + num'un burada çalışacağını varsayıyorum
Serguei Fedorov

2
@SergueiFedorov: hayır, değil
Algoman

Yanıtlar:


132

std::listÇift bağlantılı bir liste olarak uygulanan bir dizinin N. öğesine sık sık erişmeniz gerekiyorsa , muhtemelen doğru seçim değildir. std::vectorveyastd::deque da muhtemelen daha iyi olurdu.

Bununla birlikte, aşağıdakileri kullanarak N'inci öğeye bir yineleyici alabilirsiniz 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'
}

Rasgele erişim sağlamaz bir kap için, gibi std::list, std::advancearamaları operator++yineleyici üzerinde Nzamanlarda. Alternatif olarak, Standart Kitaplık uygulamanız sağlıyorsa şunları arayabilirsiniz std::next:

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

std::nextbir çağrıyı etkili bir şekilde sararak std::advance, daha Naz kod satırı ve daha az değişken değişkenle yineleyici süreleri ilerletmeyi kolaylaştırır . std::nextC ++ 11'de eklendi.


18
Rastgele erişimin olmaması nedeniyle bağlantılı bir listede arama yaparken performans cezası öderken, bir vektör veya arka arkaya veri eklemeniz veya kaldırmanız gerekirse çok daha büyük bir performans cezası ödersiniz. Soru aslında ideal kabı kendi amaçları için kullanıp kullanmadıklarına karar vermek için yeterli bilgi içermiyor.
tloach

1
std::advanceVeya kullanırken std::nextUB'yi çağırmanın kolay olduğunu belirtmek gerekir . Sınır kontrolü yoktur.
okovko

34

std::listbir indeks verilen elemanı almak için herhangi bir işlev sağlamaz. Bunu, tavsiye etmeyeceğim bir kod yazarak elde etmeye çalışabilirsiniz, çünkü sık sık yapmanız gerekiyorsa bu verimsiz olacaktır.

Tek ihtiyacın olan: std::vector. Şu şekilde kullanın:

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 

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
}

3

Belki de en verimli yol değil. Ancak listeyi bir vektöre dönüştürebilirsiniz.

#include <list>
#include <vector>

list<Object> myList;

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

Sonra [x] operatörünü kullanarak vektöre erişin.

auto x = MyVector[0];

Bunu bir yardımcı fonksiyona koyabilirsiniz:

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

Ardından yardımcı işlevi şu şekilde kullanın:

auto MyVector = ListToVector(Object);
auto x = MyVector[0];
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.