fborges22
fborges22

Reputation: 346

How to find a struct list item

I have a list of struct that is described below:

struct Files
{
    string id;
    string path;
    string chksum;
};

And a variable that contains a list of this struct that describes a file list with the fields id, path and chksum.

list<Files> myFiles;

I need to implement an function that searches if a determined filename is present in my list.

I tried to use the find_if algorithm but I am getting very strange errors, and I am not sure how to implement this efficiently.

string filename = "mytext.txt";

auto match = std::find_if(myFiles.cbegin(), myFiles.cend(), [] (const Files& s) {
  return s.path == filename;
});

if (match != myFiles.cend()) 
{
    cout << "omg my file was found!!! :D";
}
else
{
    cout << "your file is not here :(";
}

Upvotes: 1

Views: 319

Answers (2)

Casey
Casey

Reputation: 10936

You need to add filename to the capture list of the lambda:

string filename = "mytext.txt";

auto match = std::find_if(myFiles.cbegin(), myFiles.cend(), [filename] (const Files& s) {
    return s.path == filename;
});

if (match != myFiles.cend()) 
{
    cout << "omg my file was found!!! :D";
}
else
{
    cout << "your file is not here :(";
}

Upvotes: 2

Vlad from Moscow
Vlad from Moscow

Reputation: 310950

It seems that the variable filename is declared in a block scope. In this case you have to capture it. It is better to capture it by reference as for example

#include <iostream>
#include <string>
#include <list>
#include <iterator>
#include <algorithm>

struct Files
{
    std::string id;
    std::string path;
    std::string chksum;
};

int main()
{
    std::list<Files> myFiles = { { "10", "mytext.txt", "10" } };

    std::string filename = "mytext.txt";

    auto match = std::find_if( std::cbegin( myFiles ), std::cend( myFiles ), 
                               [&] ( const Files &s ) 
                               {
                                    return s.path == filename;
                               } );

    if ( match != std::cend( myFiles ) ) 
    {
        std::cout << "omg my file was found!!! :D";
    }
    else
    {
        std::cout << "your file is not here :(";
    }
}

Otherwise if the variable filename is declared in a namespace you can use the lambda as is

#include <iostream>
#include <string>
#include <list>
#include <iterator>
#include <algorithm>

struct Files
{
    std::string id;
    std::string path;
    std::string chksum;
};

std::string filename = "mytext.txt";

int main()
{
    std::list<Files> myFiles = { { "10", "mytext.txt", "10" } };


    auto match = std::find_if( std::cbegin( myFiles ), std::cend( myFiles ), 
                               [] ( const Files &s ) 
                               {
                                    return s.path == filename;
                               } );

    if ( match != std::cend( myFiles ) ) 
    {
        std::cout << "omg my file was found!!! :D";
    }
    else
    {
        std::cout << "your file is not here :(";
    }
}

Upvotes: 2

Related Questions