Search variable/item/attribute using STL in c++? - c++

There is any way to search an item or attribute or variable in C++ using STL .
We can use any container of STL providing Searching time as less as possible . Container contains pair<int,int> . i would like to search a pair p(a,x) which should return all pairs X whose p.first == Xi.first and p.second != Xi.second for all i .
e.g.
Let container is unordered_set .
unordered_set< pair<int , int > > myset =
{{1,2},{1,5},{1,6},{2,4},{3,5},{4,6},{6,7},{6,8}};
if i search for p(1,5) then it should return pair(1,2),(1,6)
if i search for p(2,4) or (3,5),(6,7) then it should return NULL i.e. nothing
if i search for p(6,7) then it should return pair(6,8)

Something along the lines of
std::vector<std::pair<int, int>>
find_nonmatching_values(const std::unordered_multimap<int, int> & thing,
int key, int value) {
std::vector<std::pair<int, int>> ret;
auto range = thing.equal_range(key);
std::copy_if(range.first, range.second, std::back_inserter(ret),
[value](const std::pair<const int, int> &p)
{ return p.second != value; });
return ret;
}
Demo. Templatizing this code is left as an exercise for the reader.

Slightly more general than T.C.s version:
#include <type_traits>
#include <iterator>
template <typename T, typename InputIterator, typename OutputIterator, typename Comparator>
void find_mismatches(InputIterator first, InputIterator last,
T const& val, OutputIterator out, Comparator comp)
{
for (; first != last; ++first)
{
auto&& f = *first;
if (!comp(f.second, val))
*out++ = f;
}
}
template <typename AssociativeCont, typename OutputIterator, typename Comparator>
void find_mismatches(AssociativeCont&& rng, typename std::remove_reference<AssociativeCont>::type::value_type const& val, OutputIterator out, Comparator comp)
{
auto range = rng.equal_range(val.first);
find_mismatches(range.first, range.second, val.second, out, comp);
}
template <typename AssociativeCont, typename OutputIterator>
void find_mismatches(AssociativeCont&& rng, typename std::remove_reference<AssociativeCont>::type::value_type const& val, OutputIterator out)
{
auto range = rng.equal_range(val.first);
find_mismatches(range.first, range.second, val.second, out, std::equal_to<decltype(val.second)>());
}
Demo. Note that you could still expand this by using a template parameter that is a pointer-to-member to a value_type's member.

Related

Symmetric difference of many sets

The symmetric difference of sets is the set of all elements that do not belong to all the sets. If the sets are already sorted, then I've come up with the solution below that uses std::set_union, std::set_intersection, and std::set_difference. But I'm not convinced that it is the cleanest way to do it. Can someone think of a better (perhaps more efficient) way that uses one simple recursion with variadic template arguments to get the result right away? Perhaps using std::set_symmetric_difference recursively? I have trouble figuring that out. Here is my solution using the above method:
#include <iostream>
#include <vector>
#include <algorithm>
template <typename Container>
std::vector<typename Container::value_type> multi_union (const Container& container) {
return container;
}
template <typename Container1, typename Container2, typename... Containers>
std::vector<typename Container1::value_type> multi_union (const Container1& container1,
const Container2& container2, const Containers&... containers) {
std::vector<typename Container1::value_type> v;
std::set_union (container1.begin(), container1.end(), container2.begin(), container2.end(),
std::back_inserter(v));
return multi_union (v, containers...);
}
template <typename Container>
std::vector<typename Container::value_type> multi_intersection (const Container& container) {
return container;
}
template <typename Container1, typename Container2, typename... Containers>
std::vector<typename Container1::value_type> multi_intersection (const Container1& container1,
const Container2& container2, const Containers&... containers) {
std::vector<typename Container1::value_type> v;
std::set_intersection (container1.begin(), container1.end(), container2.begin(),
container2.end(), std::back_inserter(v));
return multi_intersection (v, containers...);
}
template <typename Container, typename... Containers>
std::vector<typename Container::value_type> multi_symmetric_difference (const Container&
container, const Containers&... containers) {
const std::vector<typename Container::value_type>
a = multi_union (container, containers...),
b = multi_intersection (container, containers...);
std::vector<typename Container::value_type> v;
std::set_difference (a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(v));
return v;
}
int main() {
std::vector<int> a = {3,4,6,1,2}, b = {6,8,9,2}, c = {6,7,4,5,2};
std::sort (a.begin(), a.end()); std::sort (b.begin(), b.end()); std::sort (c.begin(), c.end());
const std::vector<int> s = multi_symmetric_difference (a, b, c);
for (int x : s) std::cout << x << ' '; // 1 3 4 5 7 8 9
}
Also, like std::set_symmetric_difference, multi_symmetric_difference should output to an output iterator so that the resulting container can be of any type (not just vector).

Best STL transform - like template function for ternary operators

STL defines two flavors of the transform function
The first is For unary operators:
template <class InputIterator, class OutputIterator, class UnaryOperation>
OutputIterator transform (InputIterator first1, InputIterator last1,
OutputIterator result, UnaryOperation op);
And the second is for binary operators:
template <class InputIterator1, class InputIterator2,
class OutputIterator, class BinaryOperation>
OutputIterator transform (InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, OutputIterator result,
BinaryOperation binary_op);
What is the most efficient implementation of a similiar function for a ternary operator?
EDIT:
Here is the trivial implementation I came up with, but isn't there a leaner and more elegant solution?
template <class InputIterator1, class InputIterator2, class InputIterator3,
class OutputIterator, class TrenaryOperation>
OutputIterator transform3(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator3 first3, OutputIterator result,
TrenaryOperation trenary_op)
{
while (first1 != last1) {
*result = trenary_op(*first1, *first2, *first3);
++result; ++first1; ++first2; ++first3;
}
return result;
}
A simple version of this can be achieved to create an n-ary transform like this:
template <class Functor, class OutputIterator,
class Input1, class ... Inputs>
OutputIterator transform(Functor f, OutputIterator out,
Input1 first1, Input1 last1,
Inputs ... inputs)
{
while(first1 != last1)
*out++ = f(*first1++, *inputs++...);
return out;
}
This version tries to stay as close to the existing transform as possible, taking one first/last pair of iterators and the rest are just firsts. This leaves it up to the user to make sure all the ranges are valid, just as with the binary-transform.
As for performance, I agree with ShighShagh's comment about performance not likely being an issue here. The compiler will be in a better place than you to determine what optimizations to take because each instantiation could lead to different situations that the programmer couldn't possibly know while writing this function.
Here is my take at it. I got a little carried away, which resulted in a transform function for N dimensions:
#include <iostream> // for std::cout
#include <iterator> // for std::ostream_iterator
#include <tuple> // for std::tie
#include <type_traits> // for std::enable_if
#include <vector> // for std::vector
template<typename T>
struct identity { using type = T; };
template<typename Integral, Integral... N>
struct integer_sequence {
template<Integral Offset>
struct offset : identity<integer_sequence<Integral, (N + Offset)...>> { };
};
namespace detail {
template<typename... T>
void ignore(T&&...) { }
template<std::size_t Idx, typename... T>
inline auto nth_arg(T&&... arg)
-> decltype(std::get<Idx>(std::tie(arg...))) {
return std::get<Idx>(std::tie(arg...));
}
template<std::size_t N, std::size_t... T>
struct gen_iter_indices
: gen_iter_indices<(N - 2), (N - 2), T...> { };
template<std::size_t... T>
struct gen_iter_indices<0, T...>
: identity<integer_sequence<std::size_t, T...>> { };
template<
typename... Iterator,
typename Integral,
Integral... Begin,
Integral... End
>
inline static bool eq_n(const std::tuple<Iterator...>& iters,
integer_sequence<Integral, Begin...>,
integer_sequence<Integral, End...>)
{
const bool res[] { (std::get<Begin>(iters) == std::get<End>(iters))... };
for(std::size_t i = 0; i < sizeof...(Begin); ++i) {
if(res[i]) { return true; }
}
return false;
}
template<typename... Iterator, typename Integral, Integral... Begin>
inline static void increment_n(const std::tuple<Iterator...>& iters,
integer_sequence<Integral, Begin...>)
{
ignore(++std::get<Begin>(iters)...);
}
template<
typename NaryOperation,
typename... Iterator,
typename Integral,
Integral... Begin
>
inline auto call_n(const std::tuple<Iterator...>& iters,
NaryOperation op,
integer_sequence<Integral, Begin...>)
-> decltype(op(*std::get<Begin>(iters)...))
{
return op(*std::get<Begin>(iters)...);
}
}
template<
typename OutputIter,
typename NaryOperation,
typename... InputIter,
typename = typename std::enable_if<
(2 <= sizeof...(InputIter)) && // Atleast one iterator pair
(0 == (sizeof...(InputIter) % 2)) // and multiple of two
>::type
>
static OutputIter transform_n(OutputIter out_iter,
NaryOperation op,
InputIter... in_iter)
{
using begins = typename detail::gen_iter_indices<sizeof...(InputIter)>::type;
using ends = typename begins::template offset<1>::type;
const auto iters = std::tie(in_iter...); // tuple of references to iterators
while(!detail::eq_n(iters, begins{}, ends{})) {
*out_iter = detail::call_n(iters, op, begins{});
++out_iter;
detail::increment_n(iters, begins{});
}
return out_iter;
}
Usage is simple:
int main(int argc, char** argv) {
std::vector<int> v1 { 1, 2, 3 };
std::vector<int> v2 { 4, 5, 6 };
std::vector<int> v3 { 7, 8, 9 };
std::vector<int> res { };
res.resize(3);
auto end = transform_n(
res.begin(),
[](int _1, int _2, int _3) { return _1 + _2 + _3; },
v1.begin(),
v1.end(),
v2.begin(),
v2.end(),
v3.begin(),
v3.end()
);
std::copy(res.begin(), end, std::ostream_iterator<int>(std::cout, " "));
return 0;
}
Output on ideone.
Note that in this version works with containers or different sizes, so if you know your containers will always be the same size, you can edit detail::eq_n to only check the first begin/end iterators for equality.

Function template accepting nothing less than a bidirectional iterator or a pointer

I need a function template that accepts two iterators that could be pointers. If the two arguments are random_access iterators I want the return type to be an object of
std::iterator<random_access_iterator_tag, ...> type
else a
std::iterator<bidirectional_iterator_tag, ...> type.
I also want the code to refuse
compilation if the arguments are neither a bidirectional iterator, nor a pointer. I cannot have dependency on third party libraries e.g. Boost
Could you help me with the signature of this function so that it accepts bidirectional iterators as well as pointers, but not say input_iterator, output_iterator, forward_iterators.
One partial solution I can think of is the following
template<class T>
T foo( T iter1, T iter2) {
const T tmp1 = reverse_iterator<T>(iter1);
const T tmp2 = reverse_iterator<T>(iter2);
// do something
}
The idea is that if it is not bidirectional the compiler will not let me construct a reverse_iterator from it.
Here's an example with enable_if based on iterator tags. The substitution fails if the given T doesn't have a iterator_category typedef and so that overload isn't considered during overload resolution.
Since you can't use C++11, see the reference pages for enable_if and is_same to see how you can implement it by yourself.
#include <iterator>
#include <type_traits>
#include <iostream>
#include <vector>
#include <list>
template<typename T>
typename
std::enable_if<
std::is_same<
typename T::iterator_category,
std::bidirectional_iterator_tag
>::value,
T
>::type
foo(T it)
{
std::cout << "bidirectional\n";
return it;
}
template<typename T>
typename
std::enable_if<
std::is_same<
typename T::iterator_category,
std::random_access_iterator_tag
>::value,
T
>::type
foo(T it)
{
std::cout << "random access\n";
return it;
}
// specialization for pointers
template<typename T>
T* foo(T* it)
{
std::cout << "pointer\n";
return it;
}
int main()
{
std::list<int>::iterator it1;
std::vector<int>::iterator it2;
int* it3;
std::istream_iterator<int> it4;
foo(it1);
foo(it2);
foo(it3);
//foo(it4); // this one doesn't compile, it4 is an input iterator
}
Live example.
As per #JonathanWakely's comment, we can get rid of specialization for pointers if we use std::iterator_traits. The typename T::iterator_category part then becomes
typename std::iterator_traits<T>::iterator_category
a bit simpler than previous answer, no dependency on std::enable_if:
namespace detail
{
template<class T>
T do_foo(T iter1, T iter2, std::random_access_iterator_tag t)
{
cout << "do_foo random_access" << endl;
return iter1;
}
template<class T>
T do_foo(T iter1, T iter2, std::bidirectional_iterator_tag t)
{
cout << "do_foo bidirectional" << endl;
return iter1;
}
}
template<class T>
void foo(T iter1, T iter2)
{
typename std::iterator_traits<T>::iterator_category t;
detail::do_foo(iter1, iter2, t);
}
int main (int argc, const char * argv[])
{
std::vector<int> v;
foo(v.begin(), v.end());
std::list<int> l;
foo(l.begin(), l.end());
return 0;
}
The solution also supports other iterator_categories derived from std::random_access_iterator_tag or std::bidirectional_iterator_tag (should there be any), while std::same<> checks for strict category equality.

Common code to iterate through different types of collections

Is there an elegant solution to use common code to iterate through hash_map/unordered_map and list/vector collections?
An example:
template<typename collection>
class multicast
{
public:
typedef collection collection_type;
private:
collection_type& m_channels;
public:
multicast(collection_type& channels) : m_channels(channels) { }
void operator ()(const buffer::ptr& head, const buffer::ptr& cnt)
{
for each(collection_type::value_type& ch in m_channels)
ch->send(head, cnt); /* this is where the magic should happen? */
}
}
This code obviously fails to compile when collection_type is unordered_map since collection_type::value_type is a pair so the code that access the actual value should be different: ch.second->send(head, cnt) instead of ch->send(head, cnt). So what would be the most elegant way to get rid of key part when it is not needed?
Yes:
for (auto & x : collection) { do_stuff_with(x); }
Alternatively:
for (auto it = std::begin(collection), end = std::end(collection); it != end; ++it)
{
do_stuff_with(*it);
}
If neither range-based for nor auto are available, you could write a template which takes a container C and use C::value_type and C::iterator; or you could make a template which accepts a pair of iterators of type Iter and uses std::iterator_traits<Iter>::value_type for the element value type.
Thirdly, you can use for_each and a lambda:
std::for_each(colllection.begin(), collection.end(),
[](collection::value_type & x) { do_stuff_with(x); });
To accommodate for both single-element and pair-element containers, you can build a little wrapper:
template <typename T> struct get_value_impl
{
typedef T value_type;
static value_type & get(T & t) { return t; }
};
template <typename K, typename V> struct get_value_impl<std::pair<K, V>>
{
typedef V value_type;
static value_type & get(std::pair<K,V> & p) { return p.second; }
};
template <typename T>
typename get_value_impl<T>::value_type & get_value(T & t)
{
return get_value_impl<T>::get(t);
}
Now you can use get_value(x) or get_value(*it) to get the value only.
The problem is that list/vector contains just a value, while map-s contains a pair of key-value. They are not the same thing, and to iterate the same way you shold at least define what part of the pair you are interested in.
Once defined, you essentially need a "derefence" operation that accepts an iterator, and -in case it has as a value_type a pair, return the second element, oterwise just dereference it.
// default case, returning itself
template<class T>
T& get_val(T& t) { return t; }
// case for pair (derefence for a map iterator)
template<class K, class V>
V& get_val(std::pair<const K, V>& s) { return s.second; }
// iterator dereference
template<class Iter>
decltype(get_val(*Iter()) deref_iter(const Iter& i)
{ return get_val(*i); }
Of course, const_iter version are also required, if needed.
Now:
for(auto i=container.begin(); i!=container-end(); ++i)
do_something_with(deref_iter(i));
will be the same whatever the container.

Iterate through STL sequence and associative containers using same code?

Let's say I'd like to write an algorithm that prints the value of each element in a container. The container could be a Sequence or Associative container (e.g. std::vector or std::map). In the case of a sequence, the algorithm would print the value_type. In the case of an associative type, the algorithm would print the data_type. How can I write my algorithm (only once!) so that it works with either one? Pretend that the algorithm is complex and that I don't want to repeat it for both sequence/associative versions.
For example:
template <class Iterator>
void printSequence(Iterator begin, Iterator end)
{
for (Iterator it=begin; it!=end; ++it)
std::cout << *it;
}
template <class Iterator>
void printAssociative(Iterator begin, Iterator end)
{
for (Iterator it=begin; it!=end; ++it)
std::cout << it->second;
}
template <class Iterator>
void printEither(Iterator begin, Iterator end)
{
// ????
}
The difference that you have between your two function templates is not a difference between associative containers and sequences but a difference in the part of the type that is stored.
To clarify, std::set is an associative container but would work with your printSequence function; the problem with map is not the fact that it is associative, but that the value_type is a pair an you are only interested on the second part.
The simplest thing to do is to abstract the dereferencing operation.
E.g. used like this:
#include <map>
#include <vector>
template< class X, class Y >
void test( const std::map<X, Y>& mp )
{
printEither( mp.begin(), mp.end(), MakeMapDerefence( mp ) );
}
template< class Y >
void test( const std::vector<Y>& vec )
{
printEither( vec.begin(), vec.end(), MakeSimpleDereference( vec ) );
}
Defined like this (there's a fair bit of boiler plate that's probably a boost one-liner):
template< class ReferenceType, class IteratorType >
struct SimpleDereference
{
ReferenceType operator() ( IteratorType i ) const
{
return *i;
}
};
template< class ReferenceType, class IteratorType >
struct MapDereference
{
ReferenceType operator() ( IteratorType i ) const
{
return i->second;
}
};
// Helper template function to make an appropriate SimpleDerefence instance
template< class Container >
SimpleDereference< typename Container::const_reference
, typename Container::const_iterator >
MakeSimpleDereference( const Container& )
{
return SimpleDereference< typename Container::const_reference
, typename Container::const_iterator >();
}
// Helper template function to make an appropriate SimpleDerefence instance
template< class Container >
SimpleDereference< typename Container::reference
, typename Container::iterator >
MakeSimpleDereference( Container& )
{
return SimpleDereference< typename Container::reference
, typename Container::iterator >();
}
// Helper template function to make an appropriate MapDerefence instance
template< class Container >
MapDereference< const typename Container::mapped_type&
, typename Container::const_iterator >
MakeMapDerefence( const Container& )
{
return MapDereference< const typename Container::mapped_type&
, typename Container::const_iterator >();
}
// Helper template function to make an appropriate MapDerefence instance
template< class Container >
MapDereference< typename Container::mapped_type&
, typename Container::iterator >
MakeMapDereference( Container& )
{
return MapDereference< typename Container::mapped_type&
, typename Container::iterator >();
}
#include <iostream>
#include <ostream>
template <class Iterator, class Dereference> void printEither(Iterator begin, Iterator end, Dereference deref)
{
for (; begin != end; ++begin)
{
std::cout << deref(begin);
}
}
I've whipped up an iterator adapter based on Charles' answer. I'm posting it here in case anyone finds it useful:
#include <iostream>
#include <map>
#include <vector>
#include <boost/iterator/iterator_adaptor.hpp>
//------------------------------------------------------------------------------
template <class Iterator>
void print(Iterator begin, Iterator end)
{
for (Iterator it=begin; it!=end; ++it)
std::cout << *it << "\n";
}
//------------------------------------------------------------------------------
template <class BaseIterator>
class MapDataIterator :
public boost::iterator_adaptor<
MapDataIterator<BaseIterator>,
BaseIterator,
typename BaseIterator::value_type::second_type >
{
public:
typedef typename BaseIterator::value_type::second_type& reference;
MapDataIterator() {}
explicit MapDataIterator(BaseIterator base)
: MapDataIterator::iterator_adaptor_(base) {}
private:
friend class boost::iterator_core_access;
reference dereference() const
{return this->base_reference()->second;}
};
//------------------------------------------------------------------------------
int main()
{
std::vector<int> vec;
vec.push_back(31);
vec.push_back(41);
std::map<int,int> map;
map[31] = 41;
map[59] = 26;
typedef MapDataIterator< std::map<int,int>::iterator > DataIter;
print( vec.begin(), vec.end() );
print( DataIter(map.begin()), DataIter(map.end()) );
}
This solution has the added advantage that the algorithm need not be aware of how to dereference the iterators. It is also reusable for any existing algorithm that expects a "data sequence".
I'm surprised this little critter doesn't already exist in Boost.