Я хочу разбить список элементов arbirtray по позициям на два новых списка, содержащих все четные и нечетные элементы.
Пример: с таким списком:
["a", "b", "c", "d", "e"]
howМогу ли я получить два списка, как это:
(["a", "c", "e"], ["b", "d"])
Один проход и намного меньше кода:
evensAndOdds : List a -> (List a, List a) evensAndOdds = List.foldr (\item (a, b) -> (item :: b, a)) ([], [])
Хитрость заключается в том, чтобы переключать положение элементов возвращаемого кортежа на каждой итерации, чередуя, таким образом, какой из них добавляется без необходимости отслеживатьиндекса.
Решение 1:
evensAndOdds : List a -> (List a, List a) evensAndOdds items let enum = List.indexedMap Tuple.pair items evens = List.filterMap (\(i, v) -> if modBy 2 i == 0 then Just v else Nothing) enum odds = List.filterMap (\(i, v) -> if modBy 2 i == 1 then Just v else Nothing) enum in (evens, odds)
Решение 2:
evensAndOdds : List a -> (List a, List a) evensAndOdds = List.indexedMap (\i v -> (modBy 2 i == 0, v)) >> List.partition Tuple.first >> Tuple.mapFirst (List.map Tuple.second) >> Tuple.mapSecond (List.map Tuple.second)
Вы также можете использовать рекурсивную функцию.Это может быть легче читать, чем fold, особенно для начинающих.
fold
evensAndOdds : List a -> ( List a, List a ) evensAndOdds input = case input of [] -> ( [], [] ) [ even ] -> ( [ even ], [] ) [ even, odd ] :: tail -> let ( tailEvens, tailOdds ) = evensAndOdds tail in ( even :: tailEvens, odd :: tailOdds )