2014-12-19 3 views
1

목록의 n 번째 요소에 함수를 적용 할 수 있어야합니다. 예를 들면 다음과 같이 (목록의 n 번째 요소에 함수 적용

doSomething :: (a -> a) -> Int -> [a] -> [a] 
doSomething f n xs = ys ++ [f x] ++ zs 
    where (ys, x:zs) = splitAt (n - 1) xs 

하지만 하스켈에 새로운 해요, 그래서 나는 확신 :

> doSomething (+5) 2 [1,2,3,4,5] 

내가이 작업을 수행 할 수있는 기능을 가지고 [1,7,3,4,5]

를 반환해야 하스켈의 많은 간단한 함수들)이 작업을 수행하는 훨씬 더 좋은 방법이있다.

+1

렌즈를 살펴보십시오. – jamshidh

+3

렌즈를 들여다 보면 하스켈을 처음 접한 누군가에게 최상의 아이디어가 아닐 수도 있습니다. 나는 네가 여기있는 것이 좋다고 생각한다. 좀 더 효율적인 것을 찾고 있습니까? 더 관용적입니까? 하나의 라이너? –

+0

@jamshidh 나는 렌즈를 빨리 들여다 보았다. 그러나 나는 아직 어떤 패키지없이 이것을 할 수있는 것을 선호한다. – b3036667

답변

2

; 이 선형 시간에 실행 목록의 회씩 연결은 큰 목록에 성능이 저하 될 것입니다 : 그래서

Prelude> [if i == 2 then v + 5 else v | (i, v) <- zip [1..] l] 
[1,7,3,4,5] 

doSomething은 다음과 같습니다

Prelude> let doSomething f i l = [if p == i then f v else v | (p, v) <- zip [1..] l] 
Prelude> doSomething (+5) 2 [1,2,3,4,5] 
[1,7,3,4,5] 
+0

'p == i이면 f v else v'이면 안 되나요? 그 외에도, 내가 찾고 있었던 일이 이것입니다. – b3036667

+0

예, 제 실수였습니다. 편집 됨, 감사합니다. – utdemir

3

jamshidh가 lens 패키지를 나타냄에 따라 이러한 종류의 작업을 쉽게 수행 할 수 있습니다.

> over (element 2) (+5) [1..5] 
[1,2,8,4,5] 

작동 이런 종류의 어떤에 이동, 예를 들어 나무를 통해 작동합니다 간단한 솔루션을 렌즈에 뛰어 및 선호하지 않으려면, 당신은 단지 지능형리스트를 사용할 수 있습니다

> import Data.Tree 
> let tree = Node 1 [Node 2 [], Node 3 []] 
> putStr . drawTree . fmap show $ tree 
1 
| 
+- 2 
| 
`- 3 
> putStr . drawTree . fmap show $ over (element 2) (+5) tree 
1 
| 
+- 2 
| 
`- 8 
3

당신이 시퀀스의 요소에 랜덤 액세스가 필요한 경우, 당신은하지 않을 수 있습니다 목록을 사용하고 싶습니다. 당신은, 예를 들어, 대신 Data.Vector을 사용할 수

import Data.Vector (Vector) 
import qualified Data.Vector as V 

modifyNth :: Int -> (a -> a) -> Vector a -> Vector a 
modifyNth n f = V.imap f' 
    where f' i a | i == n = f a 
       | otherwise = a 

사용 예 :

>>> modifyNth 2 (+5) (V.fromList [1,2,3,4,5]) 
fromList [1,2,8,4,5] 
2
당신은 아주 쉽게 몇 가지 수동 재귀이 작업을 수행 할 수 있으며, 그것은뿐만 아니라의 splitAt 버전보다 더 나은 수행합니다

목록 이해보다 적은 수의 임시 객체를 할당합니다.

doSomething :: (a -> a) -> Int -> [a] -> [a] 
doSomething _f _ [] = [] 
doSomething f 0 (x:xs) = f x : xs 
doSomething f n (x:xs) = x : doSomething f (n - 1) xs 

사례는 모두 매우 분명합니다. 목록이 비어 있으면 아무것도 할 수 없으므로 반환하십시오. n이 0이면 그냥 f를 호출하고 나머지를 추가합니다. 그렇지 않으면 앞면에 현재 x를 놓고 더 작은 n으로 반복 할 수 있습니다.

관련 문제