Bagaimana cara mendapatkan elemen tertentu dalam daftar, mengingat posisinya?

92

Jadi saya punya daftar:

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

Saya tidak yakin tapi saya yakin ini akan menjadi elemen "ke 0" dalam array. Apakah ada fungsi yang dapat saya gunakan yang akan mengembalikan "myObject"?

Object copy = myList.find_element(0);

?

Uji
sumber
8
Tidak ada larik - ini adalah daftar. Jika Anda ingin mengindeks dengan integer, mengapa Anda tidak menggunakan vectorsaja?
Paul J. Lucas
2
Jika Anda selalu menginginkan elemen 0, gunakan front().
Paul J. Lucas
Saya belum menguji ini, tetapi saya menganggap myList.front () + num akan berfungsi di sini
Serguei Fedorov
2
@SergueiFedorov: tidak, tidak
Algoman

Jawaban:

129

Jika Anda sering perlu mengakses elemen ke-N dari sebuah urutan std::list, yang diimplementasikan sebagai daftar tertaut ganda, mungkin bukan pilihan yang tepat. std::vectoratau std::dequemungkin lebih baik.

Karena itu, Anda bisa mendapatkan iterator ke elemen ke-N menggunakan 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'
}

Untuk penampung yang tidak menyediakan akses acak, seperti std::list, std::advancepanggilan operator++pada waktu iterator N. Atau, jika implementasi Perpustakaan Standar Anda menyediakannya, Anda dapat memanggil std::next:

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

std::nextsecara efektif membungkus panggilan ke std::advance, membuatnya lebih mudah untuk memajukan waktu iterator Ndengan lebih sedikit baris kode dan lebih sedikit variabel yang bisa berubah. std::nextditambahkan di C ++ 11.

James McNellis
sumber
18
Meskipun Anda membayar penalti kinerja dengan mencari daftar yang ditautkan karena kurangnya akses acak, Anda membayar penalti kinerja yang jauh lebih besar jika Anda perlu memasukkan atau menghapus data di tengah vektor atau deque. Pertanyaan tersebut sebenarnya tidak berisi cukup informasi untuk memutuskan apakah mereka menggunakan wadah yang ideal untuk tujuan mereka.
tloach
1
Perlu dicatat bahwa saat menggunakan std::advanceatau std::next, mudah untuk memanggil UB. Tidak ada pemeriksaan batas.
okovko
33

std::listtidak menyediakan fungsi apa pun untuk mendapatkan elemen yang diberi indeks. Anda dapat mencoba mendapatkannya dengan menulis beberapa kode, yang tidak saya rekomendasikan, karena itu tidak akan efisien jika Anda sering perlu melakukannya.

Yang Anda butuhkan adalah: std::vector. Gunakan sebagai:

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
sumber
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
sumber
3

Mungkin bukan cara yang paling efisien. Tapi Anda bisa mengubah daftar menjadi vektor.

#include <list>
#include <vector>

list<Object> myList;

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

Kemudian akses vektor menggunakan operator [x].

auto x = MyVector[0];

Anda bisa memasukkannya ke dalam fungsi pembantu:

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

Kemudian gunakan fungsi helper seperti ini:

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