2017-12-08 4 views
-2

나는 다음과 같은 코드가 있습니다목록의 하위 목록에 요소를 추가

let numbers = [[1],[2],[3],[4]] 

내가 목록 ([3])의 인덱스 2의 하위 목록에 "3"을 추가하려면,이 같은 :

(numbers !! 2) ++ [3] 

numbers = [[1],[2],[3,3],[4]] 

하지만 임 매우 혼란 : P 어떤 생각

이를 얻으려면?

+3

대형 구조의 일부만 업데이트하면 _lenses_가됩니다. 그러나 렌즈는 상당히 발전했습니다. 나는 당신이'update :: Int -> a -> [a] -> [a]'와 같은 커스텀 업데이트 함수를 쓸 것을 권한다. 재귀를 통해 구현할 수 있어야합니다. – chi

+5

목록을 업데이트하는 것으로 생각하지 마십시오. 대신 이전 목록, 위치 및 추가 할 값을 기반으로 새 목록을 계산하는 것으로 생각하십시오. –

답변

0

재귀 업데이트 기능을 작성하는 것은 당신을 위해 어려운 경우, 당신은 zip

zip [0..] [[1],[2],[3],[4]] 

와 합성 색인 배열에리스트 구조를 변환하고 다른 언어에서와 인덱스를 기반으로 CONCAT 버전을 쓸 수 있습니다 인덱스 배열

다음
appendAt n a = map (\(i,x) -> if i==n then x++[a] else x) . zip [0..] 

appendAt 2 3 numbers 
,536,

은 원하는 결과를 제공합니다.

1

다른 방법 인출 동작이며

take 2 numbers ++[(numbers !! 2) ++ [3]]++drop 3 numbers 
  1. 는 제 2 배열을 드롭 -> [1], [2]
  2. 대상 어레이 및 [3] 그것에을 찾을 -> [3] ++ [3] 복귀 [3,3]
  3. 드롭 제 3 어레이 -> [4]

    [1], [2] ++ [[3] ++ [3]] ++ [[4]] = [[1], [2], [3,3], [4]]

  4. 카이는 이미 현대 하스켈 구조의 일부에 이러한 업데이 트를 할 수있는 최선의 방법을 주석으로
0

는, 특히, lense에 콤비ix입니다 :

Prelude Control.Lens> let numbers = [[1],[2],[3],[4]] 
Prelude Control.Lens> numbers & ix 2 %~ (++[3]) 
[[1],[2],[3,3],[4]] 

(하지 마십시오 렌즈가 무서워. 주요 lens 패키지는 거대하고 종속성 무거운이지만, ix 포함한 킬러 기능의 대부분은 또한 호환 microlens package을 훨씬 작은.) 등의

0

가 언급 한 하스켈에서 당신이 일반적으로 수정하지 않는이 적용됩니다 그 자리에 데이터 구조. 대신, 당신은 그것을 분해하고, 변경 사항을 소개하고, 다시 결합하여 변경 사항을 통합하는 새로운 데이터 구조를 만듭니다.

특정 목록 요소를 변경하기 위해 목록 분리에 유용한 splitAt 함수를 찾았습니다. 변경하려는 요소가 두 번째 목록의 첫 번째 요소입니다

> splitAt 2 numbers 
([[1],[2]] , [[3],[4]]) -- spaces added to make it clearer 

주 : 인덱스 2에서 목록을 분할 예를 들어,이 목록의 다음 쌍을 생성합니다.이 같이 사용하는 거라고하는

appendSublist :: Int -> [a] -> [[a]] -> [[a]] 
appendSublist idx y lst 
    = let (a, x:b) = splitAt idx lst 
    in a ++ (x ++ y) : b 

:이 하스켈 함수로 설정 한 경우처럼

> let (a, x:b) = splitAt 2 numbers 
> a   -- initial part of list 
[[1],[2]] 
> x   -- element to change 
[3] 
> b   -- rest of list 
[[4]] 
> a ++ x : b    -- put list back together unchanged 
[[1],[2],[3],[4]] 
> a ++ (x ++ [3]) : b  -- put list together w/ modification 
[[1],[2],[3,3],[4]] 

, 그것은 아마 보일 것이다 : 당신은 편리하게이 쌍을 처리하기 위해 일치 하스켈의 패턴을 사용할 수 있습니다

> appendSublist 2 [3] numbers 
[[1],[2],[3,3],[4]] 

이 기본 패턴 :

let (a, x:b) = splitAt idx lst in a ++ (...replacement for x...) : b 

은 매우 유용하기 때문에 암기할만한 가치가 있습니다.

결국이 종류의 라이브러리에는 lens 라이브러리를 사용하는 것이 좋습니다. 렌즈는보다 간결하고 유연하며 (즉, 특정 목록 항목뿐만 아니라 모든 종류의 작업을 수행 할 수 있습니다.) 그러나 어쩌면 @ leftaroundabout의 답변에서 추측 할 수 있듯이 꽤 큰 학습 곡선이 있습니다.

관련 문제