Как переместить элемент в списке в Haskell?
Я читаю через узнать вы на Haskell и достиг места, где я пытаюсь переместить элемент в списке в голову. Я придумал то, что считаю наивным, и мне любопытно, может ли кто-нибудь показать мне, что опытный программист Haskell сделал бы вместо этого.
в этом примере у меня есть список целых чисел, и я хочу переместить элемент "4", который будет индексом "3", в начало списка.
let nums = [1, 2, 3, 4, 5]
(nums !! 3) : delete (nums !! 3) nums
возвращает [4, 1, 2, 3, 5].
что вы думаете?
5 ответов
Я бы сделал это так:
move n as = head ts : (hs ++ tail ts)
where (hs, ts) = splitAt n as
splitAt
разбивает список на заданную позицию, возвращает две части, которые создаются разбиением (здесь hs
и ts
). Элемент, который должен быть перемещен вперед, теперь находится в начале ts
. head ts
возвращает только первый элемент вектора ts
, tail ts
возвращает все но это первый элемент. Результат функции просто эти части объединены в правильном порядке:hs
соединяется с tail ts
и добавлено элементом head ts
.
опытные Haskellers вряд ли когда-либо с помощью индексации списка. Я бы использовал break, чтобы избежать повторных обходов (предполагая, что вы хотите соответствовать элементу "4", а не индексу "3"):
case break (== 4) [1, 2, 3, 4, 5] of
(a,x:xs) -> x:a ++ xs
(a,xs) -> a ++ xs
в:
Prelude Data.List> case break (== 4) [1, 2, 3, 4, 5] of (a,x:xs) -> x:a ++ xs; (a,xs) -> a ++ xs
[4,1,2,3,5]
мы можем сделать то же самое с индексированием через "splitAt":
Prelude Data.List> case splitAt 3 [1, 2, 3, 4, 5] of (a,x:xs) -> x:a ++ xs; (a,xs) -> a ++ xs
[4,1,2,3,5]
небольшая модификация решения sth:
toHead n xs = x : pre ++ post
where (pre, x:post) = splitAt n xs
Использование шаблона вместо head
n tail
там же
toHead n l = l !! n : take n l ++ drop (n+1) l
что может быть немного проще, чем использовать splitAt
.
какое совпадение?
Я читал то же самое несколько дней назад. Посмотрел его снова и написал его, как следующее.
nums !! 3 : [x | x <- nums, (x == (num !! 3)) == False]