memgraph/src/utils/algorithm.hpp
2022-03-14 15:47:41 +01:00

182 lines
6.1 KiB
C++

// Copyright 2022 Memgraph Ltd.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
// License, and you may not use this file except in compliance with the Business Source License.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
#pragma once
#include <algorithm>
#include <chrono>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include "utils/exceptions.hpp"
namespace memgraph::utils {
/**
* Outputs a collection of items to the given stream, separating them with the
* given delimiter.
*
* @param stream Destination stream.
* @param first Starting iterator of collection which items are going to be
* printed.
* @param last Ending iterator of the collection.
* @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 TIterator, typename TStreamer>
inline void PrintIterable(TStream *stream, TIterator first, TIterator last, const std::string &delim = ", ",
TStreamer streamer = {}) {
if (first != last) {
streamer(*stream, *first);
++first;
}
for (; first != last; ++first) {
*stream << delim;
streamer(*stream, *first);
}
}
/**
* 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 = {}) {
PrintIterable(&stream, iterable.begin(), iterable.end(), delim, streamer);
}
/**
* 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 <class TElement, class THash, class TEqual, class TAllocator>
bool Contains(const std::unordered_set<TElement, THash, TEqual, TAllocator> &iterable, const TElement &element) {
return iterable.find(element) != iterable.end();
}
template <class TKey, class TValue, class THash, class TKeyEqual, class TAllocator>
bool Contains(const std::unordered_map<TKey, TValue, THash, TKeyEqual, TAllocator> &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();
}
/**
* Return a reversed copy of the given collection.
* The copy is allocated using the default allocator.
*/
template <class TCollection>
TCollection Reversed(const TCollection &collection) {
return TCollection(std::rbegin(collection), std::rend(collection));
}
/**
* Return a reversed copy of the given collection.
* The copy is allocated with the given `alloc`.
*/
template <class TCollection, class TAllocator>
TCollection Reversed(const TCollection &collection, const TAllocator &alloc) {
return TCollection(std::rbegin(collection), std::rend(collection), alloc);
}
/**
* 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 memgraph::utils