Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ah-zip-utils.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
33# ifndef AH_ZIP_UTILS_H
34# define AH_ZIP_UTILS_H
35
36# include <type_traits>
37# include <tuple>
38# include <iterator>
39# include <utility>
40# include <optional>
41# include <functional>
42
82namespace Aleph
83{
84
85// ============================================================================
86// Type Traits for Container Detection
87// ============================================================================
88
89namespace uni_zip_detail
90{
91
92// Detect if type has STL-style begin()/end()
93template <typename T, typename = void>
94struct has_stl_iterator : std::false_type {};
95
96template <typename T>
98 decltype(std::declval<const T&>().begin()),
99 decltype(std::declval<const T&>().end()),
100 typename T::value_type
101>> : std::true_type {};
102
103// Detect if type has Aleph-style Iterator with has_curr()/get_curr()/next_ne()
104// Note: We check for next_ne() which is the non-exception-throwing variant used in Aleph
105template <typename T, typename = void>
106struct has_aleph_iterator : std::false_type {};
107
108template <typename T>
110 typename T::Iterator,
111 typename T::Item_Type,
112 decltype(std::declval<typename T::Iterator>().has_curr()),
113 decltype(std::declval<typename T::Iterator>().get_curr()),
114 decltype(std::declval<typename T::Iterator>().next_ne())
115>> : std::true_type {};
116
117// Get value type from container
118template <typename T, typename = void>
120
121template <typename T>
122struct container_value_type<T, std::enable_if_t<has_stl_iterator<T>::value>>
123{
124 using type = typename T::value_type;
125};
126
127template <typename T>
129 has_aleph_iterator<T>::value && !has_stl_iterator<T>::value>>
130{
131 using type = std::decay_t<typename T::Item_Type>;
132};
133
134template <typename T>
136
137// ============================================================================
138// Unified Iterator Wrapper
139// ============================================================================
140
144template <typename Container>
146{
147 typename std::decay_t<Container>::const_iterator curr_;
148 typename std::decay_t<Container>::const_iterator end_;
149
150public:
151 using value_type = typename std::decay_t<Container>::value_type;
152
153 explicit StlIteratorWrapper(const Container& c)
154 : curr_(c.begin()), end_(c.end()) {}
155
156 [[nodiscard]] bool has_curr() const noexcept { return curr_ != end_; }
157 [[nodiscard]] bool completed() const noexcept { return curr_ == end_; }
158 [[nodiscard]] auto get_curr() const { return *curr_; }
159 void next() noexcept { ++curr_; }
160};
161
165template <typename Container>
167{
168 typename std::decay_t<Container>::Iterator it_;
169
170public:
171 using value_type = std::decay_t<typename std::decay_t<Container>::Item_Type>;
172
174 : it_(c) {}
175
176 [[nodiscard]] bool has_curr() const noexcept { return it_.has_curr(); }
177 [[nodiscard]] bool completed() const noexcept { return !it_.has_curr(); }
178 [[nodiscard]] auto get_curr() const { return it_.get_curr(); }
179 void next() { it_.next_ne(); }
180};
181
185template <typename Container, typename = void>
187
188// STL containers (prefer STL if both interfaces exist)
189template <typename Container>
191 std::enable_if_t<has_stl_iterator<std::decay_t<Container>>::value>>
192{
194};
195
196// Aleph-only containers (no STL interface)
197template <typename Container>
200 has_aleph_iterator<std::decay_t<Container>>::value &&
201 !has_stl_iterator<std::decay_t<Container>>::value>>
202{
204};
205
206template <typename Container>
208
209// Static assertion helper for unsupported container types
210template <typename T>
211inline constexpr bool is_supported_container_v =
214
215} // namespace uni_zip_detail
216
217// ============================================================================
218// Sentinel type for O(1) end()
219// ============================================================================
220
228
229// ============================================================================
230// Unified Zip Iterator
231// ============================================================================
232
246template <typename... Containers>
248{
249 static_assert((uni_zip_detail::is_supported_container_v<Containers> && ...),
250 "All containers must have either STL (begin/end) or Aleph (Iterator) interface");
251
252public:
253 using value_type = std::tuple<uni_zip_detail::container_value_t<Containers>...>;
254
255private:
256 std::tuple<uni_zip_detail::iterator_wrapper_t<Containers>...> iters_;
257
258 template <size_t... Is>
259 [[nodiscard]] bool has_curr_impl(std::index_sequence<Is...>) const noexcept
260 {
261 return (... && std::get<Is>(iters_).has_curr());
262 }
263
264 template <size_t... Is>
265 [[nodiscard]] bool any_has_curr_impl(std::index_sequence<Is...>) const noexcept
266 {
267 return (... || std::get<Is>(iters_).has_curr());
268 }
269
270 template <size_t... Is>
271 [[nodiscard]] bool all_completed_impl(std::index_sequence<Is...>) const noexcept
272 {
273 return (... && std::get<Is>(iters_).completed());
274 }
275
276 template <size_t... Is>
277 [[nodiscard]] auto get_curr_impl(std::index_sequence<Is...>) const
278 {
279 return std::make_tuple(std::get<Is>(iters_).get_curr()...);
280 }
281
282 template <size_t... Is>
283 void next_impl(std::index_sequence<Is...>)
284 {
285 (std::get<Is>(iters_).next(), ...);
286 }
287
288public:
289 static constexpr size_t num_containers = sizeof...(Containers);
290
291 explicit UniZipIterator(const Containers&... cs)
292 : iters_(uni_zip_detail::iterator_wrapper_t<Containers>(cs)...) {}
293
296 {
297 return has_curr_impl(std::make_index_sequence<num_containers>{});
298 }
299
302 {
303 return any_has_curr_impl(std::make_index_sequence<num_containers>{});
304 }
305
308 {
309 return all_completed_impl(std::make_index_sequence<num_containers>{});
310 }
311
314 {
315 return all_completed();
316 }
317
318 [[nodiscard]] auto get_curr() const
319 {
320 return get_curr_impl(std::make_index_sequence<num_containers>{});
321 }
322
323 void next()
324 {
325 next_impl(std::make_index_sequence<num_containers>{});
326 }
327
328 // STL iterator interface for range-based for
329 [[nodiscard]] auto operator*() const { return get_curr(); }
330
332 {
333 next();
334 return *this;
335 }
336
338 [[nodiscard]] bool operator==(UniZipSentinel) const noexcept
339 {
340 return !has_curr();
341 }
342
343 [[nodiscard]] bool operator!=(UniZipSentinel s) const noexcept
344 {
345 return !(*this == s);
346 }
347
349 [[nodiscard]] bool operator==(const UniZipIterator& other) const noexcept
350 {
351 // Both at end (any container exhausted)
352 return !has_curr() && !other.has_curr();
353 }
354
355 [[nodiscard]] bool operator!=(const UniZipIterator& other) const noexcept
356 {
357 return !(*this == other);
358 }
359};
360
369template <typename... Containers>
371{
372 std::tuple<const std::decay_t<Containers>&...> containers_;
373
374public:
378
379 explicit UniZipView(const Containers&... cs)
380 : containers_(cs...) {}
381
383 {
384 return std::apply([](const auto&... cs) {
385 return iterator(cs...);
386 }, containers_);
387 }
388
391 {
392 return sentinel{};
393 }
394
395 [[nodiscard]] bool empty() const
396 {
397 return !begin().has_curr();
398 }
399
401 [[nodiscard]] size_t size() const
402 {
403 size_t count = 0;
404 for (auto it = begin(); it != end(); ++it)
405 ++count;
406 return count;
407 }
408};
409
410// ============================================================================
411// Factory Functions
412// ============================================================================
413
433template <typename... Containers>
434[[nodiscard]] auto uni_zip(const Containers&... cs)
435{
436 static_assert(sizeof...(Containers) >= 2,
437 "uni_zip requires at least 2 containers");
438 return UniZipView<Containers...>(cs...);
439}
440
450template <typename... Containers>
452{
454}
455
456// ============================================================================
457// Functional Operations
458// ============================================================================
459
470template <typename Pred, typename... Containers>
472{
473 auto& pred_ref = pred; // Preserve as lvalue to avoid invalidating in loop
474 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
475 if (!pred_ref(it.get_curr()))
476 return false;
477 return true;
478}
479
486template <typename Pred, typename... Containers>
488{
489 auto& pred_ref = pred;
490 auto it = uni_zip_it(cs...);
491 for (; it.has_curr(); it.next())
492 if (!pred_ref(it.get_curr()))
493 return false;
494 return it.all_completed(); // All containers exhausted = equal length
495}
496
507template <typename Pred, typename... Containers>
509{
510 auto& pred_ref = pred;
511 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
512 if (pred_ref(it.get_curr()))
513 return true;
514 return false;
515}
516
518template <typename Pred, typename... Containers>
520{
521 return uni_zip_exists(std::forward<Pred>(pred), cs...);
522}
523
530template <typename Pred, typename... Containers>
532{
533 return !uni_zip_exists(std::forward<Pred>(pred), cs...);
534}
535
545template <typename Op, typename... Containers>
546void uni_zip_for_each(Op&& op, const Containers&... cs)
547{
548 auto& op_ref = op;
549 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
550 op_ref(it.get_curr());
551}
552
562template <typename Op, typename... Containers>
564{
565 auto& op_ref = op;
566 size_t idx = 0;
567 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next(), ++idx)
568 op_ref(idx, it.get_curr());
569}
570
582template <typename T, typename Op, typename... Containers>
584{
585 auto& op_ref = op;
586 T acc = std::move(init);
587 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
588 acc = op_ref(std::move(acc), it.get_curr());
589 return acc;
590}
591
593template <typename T, typename Op, typename... Containers>
595{
596 return uni_zip_foldl(std::move(init), std::forward<Op>(op), cs...);
597}
598
609template <typename Op, typename... Containers>
610[[nodiscard]] auto uni_zip_map(Op&& op, const Containers&... cs)
611{
612 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
613 using ResultType = std::decay_t<decltype(op(std::declval<TupleType>()))>;
614
615 auto& op_ref = op;
616 std::vector<ResultType> result;
617 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
618 result.push_back(op_ref(it.get_curr()));
619 return result;
620}
621
632template <typename Pred, typename... Containers>
634{
635 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
636
637 auto& pred_ref = pred;
638 std::vector<TupleType> result;
639 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
640 {
641 auto t = it.get_curr();
642 if (pred_ref(t))
643 result.push_back(t);
644 }
645 return result;
646}
647
658template <typename Pred, typename... Containers>
660{
661 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
662
663 auto& pred_ref = pred;
664 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
665 {
666 auto t = it.get_curr();
667 if (pred_ref(t))
668 return std::optional<TupleType>(t);
669 }
670 return std::optional<TupleType>{};
671}
672
679template <typename Pred, typename... Containers>
681{
682 auto& pred_ref = pred;
683 size_t count = 0;
684 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
685 if (pred_ref(it.get_curr()))
686 ++count;
687 return count;
688}
689
696template <typename... Containers>
698{
699 size_t count = 0;
700 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
701 ++count;
702 return count;
703}
704
711template <typename... Containers>
713{
714 auto it = uni_zip_it(cs...);
715 while (it.has_curr())
716 it.next();
717 return it.all_completed(); // All exhausted = equal length
718}
719
726template <typename... Containers>
727[[nodiscard]] auto uni_zip_nth(size_t n, const Containers&... cs)
728{
729 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
730
731 size_t i = 0;
732 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next(), ++i)
733 if (i == n)
734 return std::optional<TupleType>(it.get_curr());
735 return std::optional<TupleType>{};
736}
737
744template <typename... Containers>
745[[nodiscard]] auto uni_zip_take(size_t n, const Containers&... cs)
746{
747 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
748
749 std::vector<TupleType> result;
750 result.reserve(n);
751 size_t count = 0;
752 for (auto it = uni_zip_it(cs...); it.has_curr() && count < n; it.next(), ++count)
753 result.push_back(it.get_curr());
754 return result;
755}
756
763template <typename... Containers>
764[[nodiscard]] auto uni_zip_drop(size_t n, const Containers&... cs)
765{
766 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
767
768 std::vector<TupleType> result;
769 auto it = uni_zip_it(cs...);
770
771 for (size_t i = 0; i < n && it.has_curr(); ++i)
772 it.next();
773
774 for (; it.has_curr(); it.next())
775 result.push_back(it.get_curr());
776 return result;
777}
778
785template <typename Pred, typename... Containers>
787{
788 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
789
790 auto& pred_ref = pred;
791 std::vector<TupleType> result;
792 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
793 {
794 auto t = it.get_curr();
795 if (!pred_ref(t))
796 break;
797 result.push_back(t);
798 }
799 return result;
800}
801
808template <typename Pred, typename... Containers>
810{
811 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
812
813 auto& pred_ref = pred;
814 std::vector<TupleType> result;
815 auto it = uni_zip_it(cs...);
816
817 for (; it.has_curr() && pred_ref(it.get_curr()); it.next())
818 /* skip */;
819
820 for (; it.has_curr(); it.next())
821 result.push_back(it.get_curr());
822 return result;
823}
824
831template <typename... Containers>
833{
834 return uni_zip_nth(0, cs...);
835}
836
843template <typename... Containers>
845{
846 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
847
848 std::optional<TupleType> result;
849 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
850 result = it.get_curr();
851 return result;
852}
853
860template <typename Pred, typename... Containers>
862{
863 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
864
865 auto& pred_ref = pred;
866 std::vector<TupleType> matching, non_matching;
867 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
868 {
869 auto t = it.get_curr();
870 if (pred_ref(t))
871 matching.push_back(t);
872 else
873 non_matching.push_back(t);
874 }
875 return std::make_pair(std::move(matching), std::move(non_matching));
876}
877
884template <typename... Containers>
886{
887 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
888
889 std::vector<TupleType> result;
890 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
891 result.push_back(it.get_curr());
892 return result;
893}
894
901template <typename Pred, typename... Containers>
903{
904 auto& pred_ref = pred;
905 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
906 if (!pred_ref(it.get_curr()))
907 return false;
908 return true;
909}
910
911// ============================================================================
912// ML-style Additional Operations
913// ============================================================================
914
925template <typename Op, typename... Containers>
926[[nodiscard]] auto uni_zip_mapi(Op&& op, const Containers&... cs)
927{
928 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
929 using ResultType = std::decay_t<decltype(op(size_t{}, std::declval<TupleType>()))>;
930
931 auto& op_ref = op;
932 std::vector<ResultType> result;
933 size_t idx = 0;
934 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next(), ++idx)
935 result.push_back(op_ref(idx, it.get_curr()));
936 return result;
937}
938
949template <typename Pred, typename... Containers>
951{
952 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
953
954 auto& pred_ref = pred;
955 std::vector<TupleType> result;
956 size_t idx = 0;
957 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next(), ++idx)
958 {
959 auto t = it.get_curr();
960 if (pred_ref(idx, t))
961 result.push_back(t);
962 }
963 return result;
964}
965
977template <typename T, typename Op, typename... Containers>
978[[nodiscard]] auto uni_zip_scan_left(T init, Op&& op, const Containers&... cs)
979{
980 auto& op_ref = op;
981 std::vector<T> result;
982 result.push_back(init);
983
984 T acc = std::move(init);
985 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
986 {
987 acc = op_ref(std::move(acc), it.get_curr());
988 result.push_back(acc);
989 }
990 return result;
991}
992
1003template <typename Op, typename... Containers>
1004[[nodiscard]] auto uni_zip_find_mapi(Op&& op, const Containers&... cs)
1005{
1006 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
1007 using OptType = std::decay_t<decltype(op(size_t{}, std::declval<TupleType>()))>;
1008
1009 auto& op_ref = op;
1010 size_t idx = 0;
1011 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next(), ++idx)
1012 {
1013 auto result = op_ref(idx, it.get_curr());
1014 if (result)
1015 return result;
1016 }
1017 return OptType{};
1018}
1019
1030template <typename Eq, typename... Containers>
1031[[nodiscard]] bool uni_zip_equal_by(Eq&& eq, const Containers&... cs)
1032{
1033 auto& eq_ref = eq;
1034 auto it = uni_zip_it(cs...);
1035 for (; it.has_curr(); it.next())
1036 if (!eq_ref(it.get_curr()))
1037 return false;
1038 return it.all_completed(); // All exhausted = equal length
1039}
1040
1051template <typename Tuple, typename... Containers>
1052[[nodiscard]] bool uni_zip_mem(const Tuple& target, const Containers&... cs)
1053{
1054 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
1055 if (it.get_curr() == target)
1056 return true;
1057 return false;
1058}
1059
1070template <typename Key, typename... Containers>
1071[[nodiscard]] auto uni_zip_assoc(const Key& key, const Containers&... cs)
1072{
1073 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
1074
1075 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
1076 {
1077 auto t = it.get_curr();
1078 if (std::get<0>(t) == key)
1079 return std::optional<TupleType>(t);
1080 }
1081 return std::optional<TupleType>{};
1082}
1083
1093template <typename... Containers>
1095{
1096 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
1097
1098 auto it = uni_zip_it(cs...);
1099 if (!it.has_curr())
1100 return std::optional<TupleType>{};
1101
1102 TupleType min_val = it.get_curr();
1103 it.next();
1104
1105 for (; it.has_curr(); it.next())
1106 {
1107 auto t = it.get_curr();
1108 if (t < min_val)
1109 min_val = t;
1110 }
1111 return std::optional<TupleType>(min_val);
1112}
1113
1123template <typename... Containers>
1125{
1126 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
1127
1128 auto it = uni_zip_it(cs...);
1129 if (!it.has_curr())
1130 return std::optional<TupleType>{};
1131
1132 TupleType max_val = it.get_curr();
1133 it.next();
1134
1135 for (; it.has_curr(); it.next())
1136 {
1137 auto t = it.get_curr();
1138 if (t > max_val)
1139 max_val = t;
1140 }
1141 return std::optional<TupleType>(max_val);
1142}
1143
1153template <typename... Containers>
1155{
1156 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
1157 using ResultType = std::optional<std::pair<TupleType, TupleType>>;
1158
1159 auto it = uni_zip_it(cs...);
1160 if (!it.has_curr())
1161 return ResultType{};
1162
1163 TupleType min_val = it.get_curr();
1165 it.next();
1166
1167 for (; it.has_curr(); it.next())
1168 {
1169 auto t = it.get_curr();
1170 if (t < min_val) min_val = t;
1171 if (t > max_val) max_val = t;
1172 }
1173 return ResultType(std::make_pair(min_val, max_val));
1174}
1175
1176// ============================================================================
1177// Unzip Operations (returns DynList for mixed containers)
1178// ============================================================================
1179
1180} // end namespace Aleph
1181
1182// Need DynList for unzip operations
1183# include <htlist.H>
1184
1185namespace Aleph
1186{
1187
1207template <typename Container>
1209{
1211 using T1 = std::decay_t<decltype(std::declval<PairType>().first)>;
1212 using T2 = std::decay_t<decltype(std::declval<PairType>().second)>;
1213
1216
1218 {
1219 for (const auto& p : c)
1220 {
1221 firsts.append(p.first);
1222 seconds.append(p.second);
1223 }
1224 }
1225 else
1226 {
1227 for (auto it = c.get_it(); it.has_curr(); it.next_ne())
1228 {
1229 const auto& p = it.get_curr();
1230 firsts.append(p.first);
1231 seconds.append(p.second);
1232 }
1233 }
1234
1235 return std::make_pair(std::move(firsts), std::move(seconds));
1236}
1237
1238namespace uni_unzip_detail
1239{
1240
1241template <typename Tuple, size_t... Is>
1242auto make_dynlist_tuple(std::index_sequence<Is...>)
1243{
1244 return std::make_tuple(DynList<std::tuple_element_t<Is, Tuple>>()...);
1245}
1246
1247template <typename Tuple, typename ResultTuple, size_t... Is>
1248void append_tuple_elements(const Tuple& t, ResultTuple& result, std::index_sequence<Is...>)
1249{
1250 ((std::get<Is>(result).append(std::get<Is>(t))), ...);
1251}
1252
1253} // namespace uni_unzip_detail
1254
1276template <typename Container>
1278{
1280 constexpr size_t N = std::tuple_size_v<TupleType>;
1281
1282 auto result = uni_unzip_detail::make_dynlist_tuple<TupleType>(
1283 std::make_index_sequence<N>{});
1284
1286 {
1287 for (const auto& t : c)
1289 std::make_index_sequence<N>{});
1290 }
1291 else
1292 {
1293 for (auto it = c.get_it(); it.has_curr(); it.next_ne())
1294 uni_unzip_detail::append_tuple_elements(it.get_curr(), result,
1295 std::make_index_sequence<N>{});
1296 }
1297
1298 return result;
1299}
1300
1312template <typename... Containers>
1314{
1315 using TupleType = typename UniZipIterator<std::decay_t<Containers>...>::value_type;
1316
1317 DynList<TupleType> result;
1318 for (auto it = uni_zip_it(cs...); it.has_curr(); it.next())
1319 result.append(it.get_curr());
1320 return result;
1321}
1322
1323} // end namespace Aleph
1324
1325# endif // AH_ZIP_UTILS_H
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
Iterator that traverses multiple containers (STL or Aleph) in lockstep.
std::tuple< uni_zip_detail::container_value_t< Containers >... > value_type
std::tuple< uni_zip_detail::iterator_wrapper_t< Containers >... > iters_
UniZipIterator(const Containers &... cs)
bool all_completed() const noexcept
Returns true if ALL containers are exhausted (equal length check)
bool any_has_curr() const noexcept
Returns true if ANY container still has elements (for length checking)
static constexpr size_t num_containers
auto get_curr_impl(std::index_sequence< Is... >) const
bool any_has_curr_impl(std::index_sequence< Is... >) const noexcept
bool has_curr_impl(std::index_sequence< Is... >) const noexcept
bool operator!=(const UniZipIterator &other) const noexcept
bool operator==(const UniZipIterator &other) const noexcept
Comparison with another iterator (for algorithms that need it)
bool has_curr() const noexcept
Returns true if ALL containers have current element (zip continues)
void next_impl(std::index_sequence< Is... >)
bool operator==(UniZipSentinel) const noexcept
Comparison with sentinel - iterator is "at end" when any container exhausted.
bool completed() const noexcept
bool operator!=(UniZipSentinel s) const noexcept
bool all_completed_impl(std::index_sequence< Is... >) const noexcept
UniZipIterator & operator++()
Lazy view over multiple zipped containers (STL or Aleph).
size_t size() const
Note: O(n) - iterates through all elements to count.
iterator begin() const
bool empty() const
UniZipView(const Containers &... cs)
std::tuple< const std::decay_t< Containers > &... > containers_
UniZipIterator< std::decay_t< Containers >... > iterator
typename iterator::value_type value_type
sentinel end() const noexcept
O(1) end() using sentinel.
Wrapper that provides uniform interface for Aleph iterators.
std::decay_t< Container >::Iterator it_
std::decay_t< typename std::decay_t< Container >::Item_Type > value_type
Wrapper that provides uniform interface for STL iterators.
typename std::decay_t< Container >::value_type value_type
std::decay_t< Container >::const_iterator curr_
std::decay_t< Container >::const_iterator end_
#define N
Definition fib.C:294
Singly linked list implementations with head-tail access.
Freq_Node * pred
Predecessor node in level-order traversal.
void append_tuple_elements(const Tuple &t, ResultTuple &result, std::index_sequence< Is... >)
auto make_dynlist_tuple(std::index_sequence< Is... >)
typename IteratorWrapperSelector< Container >::type iterator_wrapper_t
typename container_value_type< std::decay_t< T > >::type container_value_t
constexpr bool is_supported_container_v
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
bool eq(const C1 &c1, const C2 &c2, Eq e=Eq())
Check equality of two containers using a predicate.
bool uni_zip_traverse(Pred &&pred, const Containers &... cs)
Traverse while predicate returns true.
auto uni_zip_scan_left(T init, Op &&op, const Containers &... cs)
Scan left - fold with intermediate results.
auto uni_zip(const Containers &... cs)
Create a lazy zip view over any combination of STL/Aleph containers.
auto uni_zip_take(size_t n, const Containers &... cs)
Take first n tuples.
bool uni_zip_equal_length(const Containers &... cs)
Check if all containers have equal length.
bool uni_zip_exists(Pred &&pred, const Containers &... cs)
Check if predicate holds for any zipped tuple.
auto uni_zip_to_vector(const Containers &... cs)
Materialize zipped tuples into a vector.
auto uni_zip_min_max(const Containers &... cs)
Get both min and max in a single pass.
bool uni_zip_none(Pred &&pred, const Containers &... cs)
Check if no tuple satisfies the predicate.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:107
auto uni_zip_filteri(Pred &&pred, const Containers &... cs)
Filter with index (filteri in ML).
T uni_zip_foldl(T init, Op &&op, const Containers &... cs)
Left fold over zipped tuples.
size_t uni_zip_length(const Containers &... cs)
Get zip length (minimum of all container sizes).
auto uni_unzip_tuple(const Container &c)
Unzip a container of tuples into a tuple of DynLists.
auto uni_zip_mapi(Op &&op, const Containers &... cs)
Map with index (mapi in ML).
bool uni_zip_equal_by(Eq &&eq, const Containers &... cs)
Check equality with custom comparator.
auto uni_zip_last(const Containers &... cs)
Get last tuple.
auto uni_zip_partition(Pred &&pred, const Containers &... cs)
Partition tuples by predicate.
auto uni_zip_nth(size_t n, const Containers &... cs)
Get n-th tuple from zipped containers.
auto uni_zip_min(const Containers &... cs)
Get minimum tuple.
auto uni_unzip(const Container &c)
Unzip a container of pairs into two DynLists.
bool uni_zip_any(Pred &&pred, const Containers &... cs)
Alias for uni_zip_exists.
auto uni_zip_to_dynlist(const Containers &... cs)
Materialize a zipped view into a DynList of tuples.
static bool init
Definition hash-fct.C:47
void uni_zip_for_each(Op &&op, const Containers &... cs)
Apply operation to each zipped tuple.
auto uni_zip_max(const Containers &... cs)
Get maximum tuple.
auto uni_zip_assoc(const Key &key, const Containers &... cs)
Find value associated with key in zipped pairs (assoc in ML).
auto uni_zip_it(const Containers &... cs)
Get a unified zip iterator.
bool uni_zip_all(Pred &&pred, const Containers &... cs)
Check if predicate holds for all zipped tuples.
size_t uni_zip_count(Pred &&pred, const Containers &... cs)
Count tuples satisfying predicate.
auto uni_zip_first(const Containers &... cs)
Get first tuple.
auto uni_zip_drop_while(Pred &&pred, const Containers &... cs)
Skip tuples while predicate is true, return the rest.
auto uni_zip_find_mapi(Op &&op, const Containers &... cs)
Find and map with index (find_mapi in ML).
auto uni_zip_filter(Pred &&pred, const Containers &... cs)
Filter zipped tuples by predicate.
auto uni_zip_map(Op &&op, const Containers &... cs)
Map operation over zipped tuples.
T uni_zip_reduce(T init, Op &&op, const Containers &... cs)
Alias for uni_zip_foldl.
auto uni_zip_take_while(Pred &&pred, const Containers &... cs)
Take tuples while predicate is true.
auto uni_zip_drop(size_t n, const Containers &... cs)
Skip first n tuples, return the rest.
bool uni_zip_all_eq(Pred &&pred, const Containers &... cs)
Check if all tuples satisfy predicate AND containers have equal length.
void uni_zip_for_each_indexed(Op &&op, const Containers &... cs)
Apply operation to each tuple with index.
auto uni_zip_find_first(Pred &&pred, const Containers &... cs)
Find first tuple satisfying predicate.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
bool uni_zip_mem(const Tuple &target, const Containers &... cs)
Check if a tuple exists in the zipped sequence (mem in ML).
STL namespace.
Sentinel type for UniZipIterator end comparison.
Select appropriate wrapper based on container type.