I need some assistance with data aggregation. Functional programming is new to me and I cannot wrap my head around the Elixir way to tackle the following problem:
Consider a list of tuples:
input = ["A", "B", "C", "D", "E", "F"]
tuples = Enum.zip([input, Enum.drop(input, 1)])
# --> [{"A", "B"}, {"B", "C"}, ..., {"E", "F"}]
Consider a mock function that marks some of these tuples as valid and some not.
The function is a black box and will return different results depending on the input. The cases here are just for example.
db_mock = fn {a, b} -> case {a, b} do
{"A", "B"} -> false
{"D", "E"} -> false
_ -> true
end end
results = Enum.map(tuples, db_mock)
# --> [false, true, true, false, true]
I now want for form chains of valid tuples and group them together like so:
[["A"], ["B", "C", "D"], ["E", "F"]]
# fls, tru, tru, fls, tru
For every mismatch, a new group is started, which will be the accumulator until the next mismatch, and so on. These are also valid outcomes:
[["A", "B", "C", "D", "E"], ["F"]]
# tru, tru, tru, tru, fls
[["A"], ["B"], ["C"], ["D"], ["E"], ["F"]]
# fls, fls, fls, fls, fls
[["A", "B", "C", "D", "E", "F"]]
# tru, tru, tru, tru, tru
- The tuples need to stay in the original order, but can be shuffled during the algorithm
- I am interesed in the cuts, that caused by invalid tuples
Algorithm in Python
input = ["A", "B", "C", "D", "E", "F"]
tuples = list(zip(input, input[1:]))
results = [False, True, True, False, True]
combined = zip(tuples, results)
[first_word, *_] = input
biglist = []; smalllist = [first_word]
for (left, right), result in zip(tuples, results):
if result:
smalllist.append(right)
else:
biglist.append(smalllist)
smalllist = [right]
if len(smalllist) > 0:
biglist.append(smalllist)
print(biglist)
# [['A'], ['B', 'C', 'D'], ['E', 'F']]
What is the best way to do that?