diff --git a/README.md b/README.md index 02f59a19..a56019ff 100644 --- a/README.md +++ b/README.md @@ -6168,17 +6168,17 @@ The function 'func' is a method that takes as argument an object of the container and returns nothing. -#### ALGO\_EXTRACT(containerDest, oplistDest, containerSrc, oplistSrc, func[, arguments..]) +#### ALGO\_EXTRACT(containerDest, oplistDest, containerSrc, oplistSrc[, func[, arguments..]]) Extract the items of the container 'containerSrc' of oplist 'oplistSrc' into the 'containerDest' of oplist 'oplistDest': CLEAN (containerDest) for each item in containerSrc do - if func([arguments,] item) + [ if func([arguments,] item) ] Push item in containerDest -The function 'func' is a predicate that takes as argument an object of the +The optional function 'func' is a predicate that takes as argument an object of the container and returns a boolean that is true if the object has to be added to the other container. diff --git a/m-algo.h b/m-algo.h index 9a60fddb..a36ab558 100644 --- a/m-algo.h +++ b/m-algo.h @@ -46,13 +46,14 @@ /* Extract a subset of a container to copy into another container. USAGE: - ALGO_EXTRACT(contDst, contDstOplist, contSrc, contSrcOplist, function - [, extra arguments of function]) */ -// TODO: without 'func' parameter, extract all. -#define ALGO_EXTRACT(contD, contDop, contS, contSop, ...) \ + ALGO_EXTRACT(contDst, contDstOplist, contSrc, contSrcOplist + [, function [, extra arguments of function]]) */ +#define ALGO_EXTRACT(contD, contDop, contS, ...) \ M_IF_NARGS_EQ1(__VA_ARGS__) \ - (ALGOI_EXTRACT(contD, M_GLOBAL_OPLIST(contDop), M_GLOBAL_OPLIST(contS), contSop, __VA_ARGS__), \ - ALGOI_EXTRACT_ARG(contD, M_GLOBAL_OPLIST(contDop), M_GLOBAL_OPLIST(contS), contSop, __VA_ARGS__ )) + (ALGOI_EXTRACT(contD, M_GLOBAL_OPLIST(contDop), M_GLOBAL_OPLIST(contS), __VA_ARGS__), \ + M_IF_NARGS_EQ2(__VA_ARGS__) \ + (ALGOI_EXTRACT_FUNC(contD, M_GLOBAL_OPLIST(contDop), M_GLOBAL_OPLIST(contS), __VA_ARGS__), \ + ALGOI_EXTRACT_ARG(contD, M_GLOBAL_OPLIST(contDop), M_GLOBAL_OPLIST(contS), __VA_ARGS__ ))) /* Perform a Reduce operation over a container. @@ -786,6 +787,15 @@ #define ALGOI_EXTRACT(contDst, contDstOplist, \ + contSrc, contSrcOplist) do { \ + M_CALL_CLEAN(contDstOplist, contDst); \ + for M_EACH(item, contSrc, contSrcOplist) { \ + M_CALL_PUSH(contDstOplist, contDst, *item); \ + } \ + M_IF_METHOD(REVERSE, contDstOplist) (M_CALL_REVERSE(contDstOplist, contDstOplist);, ) \ + } while (0) + +#define ALGOI_EXTRACT_FUNC(contDst, contDstOplist, \ contSrc, contSrcOplist, \ condFunc) do { \ M_CALL_CLEAN(contDstOplist, contDst); \ diff --git a/tests/test-malgo.c b/tests/test-malgo.c index 0099b23c..759c2669 100644 --- a/tests/test-malgo.c +++ b/tests/test-malgo.c @@ -379,14 +379,26 @@ static void test_extract(void) list_int_init (l); for(int i = -100; i < 100; i++) list_int_push_back (l, i); + list_int_reverse(l); array_int_t a; array_int_init(a); + + ALGO_EXTRACT(a, ARRAY_OPLIST(array_int), l, LIST_OPLIST(list_int)); + assert(array_int_size(a) == 200); + assert(*array_int_get(a, 0) == -100); + assert(*array_int_get(a, 199) == 99); + #define cond(d) ((d) > 0) ALGO_EXTRACT(a, ARRAY_OPLIST(array_int), l, LIST_OPLIST(list_int), cond); assert(array_int_size(a) == 99); + assert(*array_int_get(a, 0) == 1); + assert(*array_int_get(a, 98) == 99); + #define cond2(c, d) ((d) > (c)) ALGO_EXTRACT(a, ARRAY_OPLIST(array_int), l, LIST_OPLIST(list_int), cond2, 10); assert(array_int_size(a) == 89); + assert(*array_int_get(a, 0) == 11); + assert(*array_int_get(a, 88) == 99); int dst = 0; #define inc(d, c) (d) += (c)