วิธีการรับองค์ประกอบบางอย่างในรายการโดยได้รับตำแหน่ง?


95

ฉันมีรายการ:

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

ฉันไม่แน่ใจ แต่ฉันมั่นใจว่านี่จะเป็นองค์ประกอบ "0" ในอาร์เรย์ มีฟังก์ชันใดบ้างที่ฉันสามารถใช้ที่จะส่งคืน "myObject"?

Object copy = myList.find_element(0);

เหรอ?


8
ไม่มีอาร์เรย์ - เป็นรายการ หากคุณต้องการจัดทำดัชนีด้วยจำนวนเต็มทำไมคุณไม่ใช้vectorแทน
Paul

2
หากคุณต้องการเสมอองค์ประกอบ 0, front()การใช้งาน
Paul

ฉันไม่ได้ทดสอบนี้ แต่ฉันจะถือว่า myList.front () + NUM จะทำงานที่นี่
Serguei Fedorov

2
@SergueiFedorov: ไม่มันไม่
Algoman

คำตอบ:


132

หากคุณจำเป็นต้องเข้าถึงองค์ประกอบ N ของลำดับstd::listซึ่งถูกนำมาใช้เป็นรายการที่เชื่อมโยงแบบทวีคูณบ่อยครั้งอาจไม่ใช่ทางเลือกที่ถูกต้อง std::vectorหรือstd::dequeน่าจะดีกว่า

ที่กล่าวว่าคุณสามารถรับตัววนซ้ำไปยังองค์ประกอบ Nth โดยใช้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'
}

สำหรับภาชนะที่ไม่ได้ให้การเข้าถึงแบบสุ่มเช่นstd::list, std::advanceเรียกร้องoperator++ในการทำซ้ำโดยNครั้ง อีกวิธีหนึ่งหากการใช้งาน Standard Library ของคุณมีให้คุณสามารถโทรstd::next:

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

std::nextมีประสิทธิภาพในการปิดการโทรstd::advanceทำให้ง่ายต่อการเลื่อนNเวลาตัววนซ้ำโดยมีบรรทัดโค้ดน้อยลงและตัวแปรที่เปลี่ยนแปลงน้อยลง std::nextถูกเพิ่มใน C ++ 11


18
ในขณะที่คุณจ่ายค่าปรับประสิทธิภาพในการค้นหารายการที่เชื่อมโยงเนื่องจากไม่มีการเข้าถึงแบบสุ่มคุณจะต้องจ่ายค่าปรับประสิทธิภาพที่ใหญ่กว่ามากหากคุณจำเป็นต้องแทรกหรือลบข้อมูลที่อยู่ตรงกลางของเวกเตอร์หรือ deque คำถามไม่มีข้อมูลเพียงพอที่จะตัดสินใจได้ว่าพวกเขากำลังใช้คอนเทนเนอร์ที่เหมาะสำหรับวัตถุประสงค์ของพวกเขาหรือไม่
tloach

1
เป็นที่น่าสังเกตว่าเมื่อใช้std::advanceหรือstd::nextเรียกใช้ UB ได้ง่าย ไม่มีการตรวจสอบขอบเขต
okovko

34

std::listไม่มีฟังก์ชันใด ๆ ในการรับองค์ประกอบที่ได้รับดัชนี คุณอาจลองใช้มันโดยเขียนโค้ดซึ่งฉันไม่แนะนำเพราะมันจะไม่มีประสิทธิภาพถ้าคุณต้องทำบ่อยๆ

สิ่งที่คุณต้องการคือ: std::vector. ใช้เป็น:

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

อาจจะไม่ใช่วิธีที่มีประสิทธิภาพสูงสุด แต่คุณสามารถแปลงรายการเป็นเวกเตอร์ได้

#include <list>
#include <vector>

list<Object> myList;

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

จากนั้นเข้าถึงเวกเตอร์โดยใช้ตัวดำเนินการ [x]

auto x = MyVector[0];

คุณสามารถใส่ไว้ในฟังก์ชันตัวช่วย:

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

จากนั้นใช้ funciton ตัวช่วยดังนี้:

auto MyVector = ListToVector(Object);
auto x = MyVector[0];
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.