14

In C#, if I have a List of objects (e.g. List myObjectList), I can get a subset of that list via:

anotherMyObjectList = myObjectList.Where(x => x.isSomething()).Select(x => x).ToList();

Assuming I don't want to use a 3rd party C++ LINQ library (only standard library and maybe boost), what's the best way to do this in C++? It would be easy to write a function for each instance where I want to do this, but it would be better to know what framework exists to perform this type of operation.

If the answer is different in C++98, C++0x or C++11, it would be good to know the differences.

Jeff
  • 1,315
  • 2
  • 17
  • 30
  • 1
    [for_each](http://msdn.microsoft.com/en-us/library/c4x1w65f.aspx) – Travis J Aug 31 '13 at 17:20
  • I thought we can use `LINQ` in all the languages which `.NET` supports including `C#, Visual C++ and VB.NET`? – King King Aug 31 '13 at 17:25
  • @KingKing You have a valid point. But to me it sounds like the OP wants to do it with native C++, not C++/CLI. – Theodoros Chatzigiannakis Aug 31 '13 at 17:28
  • Yes, native C++. I didn't make that clear. – Jeff Aug 31 '13 at 17:31
  • If so, I don't think there is an easy solution for the OP. If we can use LINQ in native C++, we can also use LINQ in all other languages: Java, PHP, Javascript, ... LINQ is a feature of .NET (not a language). However I hope other languages will be used in their `framework` supporting a `LINQ-like` feature in future. – King King Aug 31 '13 at 17:32
  • Since there is a native javascript implementation for the Rx framework, there may be things out there specific to native c++. A very quick google search dug up this: http://channel9.msdn.com/Shows/C9-GoingNative/GoingNative-9-LINQ-for-C-Native-Rx-RxC-Meet-Aaron-Lahman. It may be interesting to watch. – Alex Aug 31 '13 at 18:08
  • Look at this [question](http://stackoverflow.com/questions/232222/is-there-a-linq-library-for-c). – Vladimir Aug 31 '13 at 18:11

3 Answers3

6

In C++11, using boost you can do something like this:

// assumming myObjectList is a vector of someObj type
std::vector<someObj> myObjectList = { ... };
auto result = myObjectList | boost::adaptors::filtered([](const someObj& x) { return x.isSomething(); });
std::vector<someObj> anotherMyObjectList(boost::begin(result), boost::end(result));
Paul Fultz II
  • 17,682
  • 13
  • 62
  • 59
3

You can use "ccplinq" :

using namespace cpplinq;
int ints[] = {3,1,4,1,5,9,2,6,5,4};
auto result = from_array (ints)
    >> where ([](int i) {return i/2 == 0;}) 
    >> select ([](int i) {std::stringstream s; s << i; return s.str();})
    >> to_list ();
Ehsan Keramat
  • 164
  • 2
  • 6
3

You can use std::copy_if() to create a subset of a container:

#include <algorithm>
#include <iterator>
#include <list>

std::list<object> myObjectList, anotherMyObjectList;

// fill myObjectList somehow

std::copy_if(cbegin(myObjectList),
             cend(myObjectList),
             std::back_inserter(anotherMyObjectList),
             [](const object& o) { return o.IsSomething(); }); 

or if you're using C++98/03:

#include <algorithm>
#include <iterator>
#include <list>

std::list<object> myObjectList, anotherMyObjectList;

// fill myObjectList somehow

struct is_something {
    bool operator()(const object&) {
        return object.IsSomething();
    }
};

std::copy_if(myObjectList.cbegin()
             myObjectList.cend(),
             std::back_inserter(anotherMyObjectList),
             is_something());
Ferruccio
  • 98,941
  • 38
  • 226
  • 299