簡體   English   中英

在遍歷列表時,如何跟蹤稍后要刪除的列表元素?

[英]When iterating through a list, how do I keep track of a list element to be deleted later on?

在這個例子中,我構建了一個包含4個Person對象的鏈表 ,每個對象都有一個年齡 我想遍歷人員列表,跟蹤最年輕的人,然后從列表中刪除該人。

這是我到目前為止所擁有的

#include <iostream>
#include <vector>
#include <list>

struct Person
{
    Person(int x): age(x) {}

    int age;
};

int main() {

    // Create 4 Person instances
    Person p1 = Person(50);
    Person p2 = Person(35);
    Person p3 = Person(99);
    Person p4 = Person(17);

    // Build a list of persons
    std::list<Person> persons = {p1, p2, p3, p4};

    // Delete the list-element of the youngest person
    int minAge = 999;            // track the lowest age so far
    Person* youngin = nullptr;  // track the person with the lowest age so far

    // Iterate through each person in the list, looking for someone with a lower age than all previous
    for(auto const &p : persons){
        if(p.age < minAge){
            std::cout << "Found someone younger. Age: " << p.age << std::endl;

            // Update minAge and youngin
            minAge = p.age;
            // youngin = ???;
        }
    }

    // Delete the youngest person from the list
    // persons.erase(youngin);

    return 0;
}

我如何1)保留一個指針(我認為?)給最年輕的人“到目前為止”和2)從結尾的列表中刪除該元素?


UPDATE

我似乎過度簡化了我的最小可重復性示例。 @NathanOliver似乎對我提出的問題有最好的解決方案,所以我會選擇他作為被接受者,但是如果有人願意幫助我,

假設列表中沒有第5個人,

Person p5 = Person(30);

現在,如何識別列表中4個人中哪個人的年齡最接近p5 ,然后從列表中刪除該人? (在這種情況下,應該識別並刪除p2 。)我沒有看到如何使用std::min_element將Nathan的解決方案應用於這種情況。

干杯

您可以使用標准算法和lambda來完成此任務。 std::min_element可用於查找最小元素,並且它返回的迭代器可以傳遞給列表erase成員函數以將其從列表中刪除。 那看起來像

persons.erase(std::min_element(persons.begin(), 
                               persons.end(), 
                               [](auto const& lhs, auto const& rhs){ return lhs.age < rhs.age; }));

如果你需要在處理它之前使用最小值,你可以分開調用

auto min_it = std::min_element(persons.begin(), 
                               persons.end(), 
                               [](auto const& lhs, auto const& rhs){ return lhs.age < rhs.age; }));
//use min_it here
person.erase(min_it); // get rid of the minimum

更新:

您仍然可以使用min_element來查找元素,我們只需要找到最小差異而不是最小元素。 我們只需要將lambda更改為比較年齡和值的差異,而不是僅僅考慮年齡。

Person p5 = Person(30);
persons.erase(std::min_element(persons.begin(), 
                               persons.end(), 
                               [&](auto const& lhs, auto const& rhs){ 
                                   return std::abs(lhs.age - p5.age) < std::abs(rhs.age - p5.age);
                               }));

我在lambda中使用[&]因此它通過引用捕獲p5 ,因此我們可以計算差異。 您可以在此實例中看到它正常工作。

p的類型是std::list<Person>::iterator (因為它需要是一個“節點”類,在大多數情況下存儲指向下一個節點的指針和節點的值)。

std::list::erase接受一個迭代器,而for循環取消引用迭代器,所以你沒有得到迭代器。

因此,您需要使用std::list::beginstd::list::end來獲取迭代器。

typename std::list<Person>::iterator youngin;  // track the person with the lowest age so far
// Or:
decltype(persons.cbegin()) youngin;

// Iterate through each person in the list, looking for someone with a lower age than all previous
for (auto it = persons.cbegin(); it != persons.cend(); ++it){
    if (p->age < minAge) {
        std::cout << "Found someone younger. Age: " << p.age << std::endl;

        // Update minAge and youngin
        minAge = p->age;
        youngin = it;
    }
}

// Delete the youngest person from the list
persons.erase(youngin);

如果您不必使用指針,則此代碼應該:

int main() {
    // Build a list of persons
    std::list<Person> persons = {Person(50), Person(35), Person(99), Person(17)};

    Person yongestPerson = persons[0];

    // looking for someone with a lower age than all previous yongestPerson
    for(persons p : persons){
        if(p.age < yongestPerson.age){
            std::cout << "Found someone younger. Age: " << p.age << std::endl;

            // Update minAge and youngin
            yongestPerson = p
        }
    }

    // Delete the youngest person from the list
    persons.remove(yongestPerson);

    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM