rec/fplus/sets.hpp

205 lines
7.0 KiB
C++
Raw Permalink Normal View History

2020-03-18 06:42:46 +00:00
// Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
// https://github.com/Dobiasd/FunctionalPlus
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#pragma once
#include <fplus/container_common.hpp>
#include <algorithm>
#include <set>
#include <unordered_set>
namespace fplus
{
// API search type: set_includes : (Set a, Set a) -> Bool
// fwd bind count: 1
// Checks if every element of the second set is also present in the first set.
// Also known as is_subset_of.
template <typename SetType>
bool set_includes(const SetType& set1, const SetType& set2)
{
return std::includes(std::begin(set1), std::end(set1),
std::begin(set2), std::end(set2));
}
// API search type: unordered_set_includes : (Unordered_Set a, Unordered_Set a) -> Bool
// fwd bind count: 1
// Checks if every element of the second unordered_set
// is also present in the first unordered_set.
// Also known as is_subset_of.
template <typename UnorderSetType>
bool unordered_set_includes(const UnorderSetType& set1,
const UnorderSetType& set2)
{
auto first_not_included = std::find_if(set2.begin(), set2.end(),
[&](const typename UnorderSetType::value_type& x)
-> bool { return set1.find(x) == set1.end();});
return first_not_included == set2.end();
}
// API search type: set_merge : (Set a, Set a) -> Set a
// fwd bind count: 1
// Returns the union of two given sets.
template <typename SetType>
SetType set_merge(const SetType& set1, const SetType& set2)
{
SetType result;
auto itOut = internal::get_back_inserter(result);
std::merge(std::begin(set1), std::end(set1),
std::begin(set2), std::end(set2),
itOut);
return result;
}
// API search type: unordered_set_merge : (Unordered_Set a, Unordered_Set a) -> Unordered_Set a
// fwd bind count: 1
// Returns the union of two given sets.
template <typename UnorderSetType>
UnorderSetType unordered_set_merge(const UnorderSetType& set1, const UnorderSetType& set2)
{
UnorderSetType result;
auto itOut = internal::get_back_inserter(result);
std::copy(std::begin(set1), std::end(set1), itOut);
std::copy(std::begin(set2), std::end(set2), itOut);
return result;
}
// API search type: set_intersection : (Set a, Set a) -> Set a
// fwd bind count: 1
// Returns the intersection of both sets.
template <typename SetType>
SetType set_intersection(const SetType& set1, const SetType& set2)
{
SetType result;
auto itOut = internal::get_back_inserter(result);
std::set_intersection(std::begin(set1), std::end(set1),
std::begin(set2), std::end(set2),
itOut);
return result;
}
// API search type: unordered_set_intersection : (Unordered_Set a, Unordered_Set a) -> Unordered_Set a
// fwd bind count: 1
// Returns the intersection of both unordered_sets.
template <typename UnorderSetType>
UnorderSetType unordered_set_intersection(
const UnorderSetType& set1, const UnorderSetType& set2)
{
UnorderSetType result;
auto itOut = internal::get_back_inserter(result);
std::copy_if(std::begin(set2), std::end(set2),
itOut, [&](const typename UnorderSetType::value_type &x)
-> bool {return set1.find(x) != set1.end();});
return result;
}
// API search type: set_is_disjoint : (Set a, Set a) -> Bool
// fwd bind count: 1
// Checks if two sets are disjoint.
template <typename SetType>
bool set_is_disjoint(const SetType& set1, const SetType& set2)
{
return set_intersection(set1, set2).empty();
}
// API search type: unordered_set_is_disjoint : (Unordered_Set a, Unordered_Set a) -> Bool
// fwd bind count: 1
// Checks if two unordered_sets are disjoint.
template <typename UnorderSetType>
bool unordered_set_is_disjoint(
const UnorderSetType& set1, const UnorderSetType& set2)
{
return unordered_set_intersection(set1, set2).empty();
}
// API search type: set_difference : (Set a, Set a) -> Set a
// fwd bind count: 1
// Returns the elements in set1 that are not present in set2.
template <typename SetType>
SetType set_difference(const SetType& set1, const SetType& set2)
{
SetType result;
auto itOut = internal::get_back_inserter(result);
std::set_difference(std::begin(set1), std::end(set1),
std::begin(set2), std::end(set2),
itOut);
return result;
}
// API search type: unordered_set_difference : (Unordered_Set a, Unordered_Set a) -> Unordered_Set a
// fwd bind count: 1
// Returns the elements in unordered_set1
// that are not present in unordered_set2.
template <typename UnorderSetType>
UnorderSetType unordered_set_difference(const UnorderSetType& set1,
const UnorderSetType& set2)
{
UnorderSetType result;
auto itOut = internal::get_back_inserter(result);
std::copy_if(std::begin(set1), std::end(set1),
itOut, [&](const typename UnorderSetType::value_type &x)
-> bool {return set2.find(x) == set2.end();});
return result;
}
// API search type: set_symmetric_difference : (Set a, Set a) -> Set a
// fwd bind count: 1
// Returns the symmetric difference of both sets.
template <typename SetType>
SetType set_symmetric_difference(const SetType& set1, const SetType& set2)
{
SetType result;
auto itOut = internal::get_back_inserter(result);
std::set_symmetric_difference(std::begin(set1), std::end(set1),
std::begin(set2), std::end(set2),
itOut);
return result;
}
// API search type: unordered_set_symmetric_difference : (Unordered_Set a, Unordered_Set a) -> Unordered_Set a
// fwd bind count: 1
// Returns the symmetric difference of both unordered_sets.
template <typename UnorderSetType>
UnorderSetType unordered_set_symmetric_difference(
const UnorderSetType& set1, const UnorderSetType& set2)
{
UnorderSetType result;
auto itOut = internal::get_back_inserter(result);
std::copy_if(std::begin(set1), std::end(set1),
itOut, [&](const typename UnorderSetType::value_type &x)
-> bool {return set2.find(x) == set2.end();});
std::copy_if(std::begin(set2), std::end(set2),
itOut, [&](const typename UnorderSetType::value_type &x)
-> bool {return set1.find(x) == set1.end();});
return result;
}
// API search type: sets_intersection : [Set a] -> Set a
// fwd bind count: 0
// Returns the intersection of the given sets.
// Also known as intersect_many.
// For performance try to sort the inputs sets prior, ascendending by size.
template <typename ContainerIn,
typename SetType = typename ContainerIn::value_type>
SetType sets_intersection(const ContainerIn& sets)
{
return fold_left_1(set_intersection<SetType>, sets);
}
// API search type: unordered_sets_intersection : [Unordered_Set a] -> Unordered_Set a
// fwd bind count: 0
// Returns the intersection of the given unordered_sets.
// Also known as intersect_many.
template <typename ContainerIn,
typename UnordSetType = typename ContainerIn::value_type>
UnordSetType unordered_sets_intersection(const ContainerIn& sets)
{
return fold_left_1(unordered_set_intersection<UnordSetType>, sets);
}
} // namespace fplus