2017-12-23 4 views
-3
dropnth' :: [a] -> Int -> [a] 
dropnth' xs n = foldl (\a b -> if (last a) == xs!!n then a else b ++ []) [head xs] xs 

나는 foldl을 사용하여 "목록의 모든 n 번째 요소 삭제"문제를 해결하려고했지만 오류가 발생합니다. 어떻게해야합니까?foldl을 사용하여 목록의 n 번째 요소를 제거하는 방법은 무엇입니까?

오류 : The error

+6

"오류가 발생했습니다."매우 도움이되지 않습니다. 게시물이 아닌 이미지에 전체 오류 메시지를 게시하십시오. – Zpalmtree

+3

'head, tail, !!'는 위험 할 정도로 부분적이므로 가능한 한 항상 피하는 것이 좋습니다. – chi

+0

이 목적을 위해서'foldl'을 사용해서는 안됩니다. 코드의 효율성이 낮고 게으르지 않은 코드를 얻을 수 있습니다. 'foldr'로 훨씬 더 잘할 수 있지만, 좀 더 영리해야합니다. – dfeuer

답변

4

a 이 아마도 당신이 이미 삭제하지 않기로 결정 한 요소입니다. 그런 다음 a의 마지막 요소가 아닌 의 다음 요소 (아마도 b)를 삭제할지 여부를 결정해야합니다.

b ++ []b 요소를 삭제하지 않고 대신 a 목록에 추가하기로 결정했다고 표시하기위한 것입니다. 이것은 실제로 a ++ [b]로 작성되었습니다.

dropnth' :: Eq a => [a] -> Int -> [a] 
dropnth' xs n = foldl (\a b -> if b == xs!!n then a else a ++ [b]) [head xs] xs 

xs!!nxs의 n 번째 요소를 찾아 내고, 그것과 비교하는 일의 가치, 즉 동일 여부를 결정 찾을 수 있습니다 :

이 적어도 컴파일이 코드 조각을 작성하는 나를 수 있습니다 뭔가의 위치. Eq a을 보면, 목록 값을 비교하고 있음을 알 수 있습니다. foldlzip [0..]과 같이 어딘가에서 항목의 위치를 ​​가져야합니다.

dropnth' :: [a] -> Int -> [a] 
dropnth' xs n = foldl (\a (i, b) -> if mod i n == 0 then a else a ++ [b]) [head xs] (zip [0..] xs) 

목록 끝에 요소를 추가하면 전체 목록을 다시 작성해야합니다. 끝에서 목록을 작성하는 것이 훨씬 더 효율적입니다. 그러나이 경우 우리는 사용 사례에 대해보다 전문화 된 목록 작업을 사용할 수도 있습니다.

dropnth' :: [a] -> Int -> [a] 
dropnth' xs n = [b | (i, b) <- zip [0..] xs, mod i n > 0] 

이제 초기 요소도 삭제합니다. 아마 그것이 당신이 원하는 것입니까? 또는 zip[1..]으로 설정하고 대신 모든 십자선을 왼쪽으로 이동하십시오.

일반적으로 Int -> [a] -> [a]과 같은 서명을 입력하십시오.

관련 문제