memgraph/src/utils/algorithm.hpp
Marin Tomic 28ba872668 Implement single node two-sided BFS
Reviewers: mculinovic, teon.banek, ipaljak, buda, msantl

Reviewed By: teon.banek

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D1567
2018-08-29 12:56:39 +02:00

152 lines
4.6 KiB
C++

#pragma once
#include <algorithm>
#include <chrono>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include "utils/exceptions.hpp"
namespace utils {
/**
* Outputs a collection of items to the given stream, separating them with the
* given delimiter.
*
* @param stream Destination stream.
* @param iterable An iterable collection of items.
* @param delim Delimiter that is put between items.
* @param streamer Function which accepts a TStream and an item and
* streams the item to the stream.
*/
template <typename TStream, typename TIterable, typename TStreamer>
inline void PrintIterable(TStream &stream, const TIterable &iterable,
const std::string &delim = ", ",
TStreamer streamer = {}) {
bool first = true;
for (const auto &item : iterable) {
if (first)
first = false;
else
stream << delim;
streamer(stream, item);
}
}
/**
* Outputs a collection of items to the given stream, separating them with the
* given delimiter.
*
* @param stream Destination stream.
* @param iterable An iterable collection of items.
* @param delim Delimiter that is put between items.
*/
template <typename TStream, typename TIterable>
inline void PrintIterable(TStream &stream, const TIterable &iterable,
const std::string &delim = ", ") {
PrintIterable(stream, iterable, delim,
[](auto &stream, const auto &item) { stream << item; });
}
/**
* Finds a mapping if it exists for given key or returns the provided value.
*
* @param map A map-like container which has the `find` method.
* @param key Key to look for in the map.
* @param or_value Value to use if the key is not in the map.
* @return Pair of value and a boolean indicating whether the key was in the
* map.
*/
template <class TMap, class TKey, class TVal>
inline std::pair<TVal, bool> FindOr(const TMap &map, const TKey &key,
TVal &&or_value) {
auto it = map.find(key);
if (it != map.end()) return {it->second, true};
return {std::forward<TVal>(or_value), false};
}
/**
* Returns the *copy* of the first element from an iterable.
*
* @param iterable An iterable collection of values.
* @return The first element of the `iterable`.
* @exception BasicException is thrown if the `iterable` is empty.
*/
template <class TIterable>
inline auto First(TIterable &&iterable) {
if (iterable.begin() != iterable.end()) return *iterable.begin();
throw utils::BasicException("Empty iterable");
}
/**
* Returns the *copy* of the first element from an iterable.
*
* @param iterable An iterable collection of values.
* @param empty_value Value to return if the `iterable` is empty.
* @return The first element of the `iterable` or the `empty_value`.
*/
template <class TVal, class TIterable>
inline TVal First(TIterable &&iterable, TVal &&empty_value) {
if (iterable.begin() != iterable.end()) return *iterable.begin();
return empty_value;
}
template <typename TElement>
inline bool Contains(const std::unordered_set<TElement> &iterable,
const TElement &element) {
return iterable.find(element) != iterable.end();
}
template <typename TKey, typename TValue>
inline bool Contains(const std::unordered_map<TKey, TValue> &iterable,
const TKey &key) {
return iterable.find(key) != iterable.end();
}
/**
* Returns `true` if the given iterable contains the given element.
*
* @param iterable An iterable collection of values.
* @param element The sought element.
* @return `true` if element is contained in iterable.
* @tparam TIiterable type of iterable.
* @tparam TElement type of element.
*/
template <typename TIterable, typename TElement>
inline bool Contains(const TIterable &iterable, const TElement &element) {
return std::find(iterable.begin(), iterable.end(), element) != iterable.end();
}
/**
* Returns a *copy* of a collection with its elements in reversed order.
*
* @param collection Collection to be reversed.
*/
template <class TCollection>
TCollection Reversed(const TCollection &collection) {
return TCollection(std::rbegin(collection), std::rend(collection));
}
/**
* Converts a (beginning, end) pair of iterators into an iterable that can be
* passed on to itertools.
*/
template <typename TIterator>
class Iterable {
public:
Iterable(TIterator &&begin, TIterator &&end)
: begin_(std::forward<TIterator>(begin)),
end_(std::forward<TIterator>(end)) {}
auto begin() { return begin_; };
auto end() { return end_; };
private:
TIterator begin_;
TIterator end_;
};
} // namespace utils