2014-11-17 2 views

답변

2

대상 목록의 모든 두 번째 요소를 삭제하고 zip을 사용하는 도우미 함수를 사용하여이를 수행하는 한 가지 방법이 있습니다. 목록에 이상한 길이가 있어도 아직 질문에 정의되어 있지 않기 때문에 원하는 동작을하지 못할 수 있습니다.

-- This is just from ghci 

let my_list = ["Questions", "that", "may", "already", "have", "your", "correct", "answer"] 

let dropEvery [] _ = [] 
let dropEvery list count = (take (count-1) list) ++ dropEvery (drop count list) count 

zip (dropEvery my_list 2) $ dropEvery (tail my_list) 2 

[("Questions","that"),("may","already"),("have","your"),("correct","answer") 

도우미 기능은 같은 생각의 많은 다른 구현, 더 나은 재귀 최적화 특성을 가진 아마 많은있다 99 Questions.에서 질문 # 6에서 가져옵니다.

dropEvery을 이해하려면 각각 takedrop이 무엇인지 기억하는 것이 좋습니다. take k some_listk의 항목을 some_list으로 취합니다. 한편 drop k some_list은 첫 번째 k 항목을 삭제합니다.

N 번째 요소를 모두 삭제하려면 N-1 개 요소를 계속 실행 한 다음 하나를 삭제하고 완료 될 때까지 동일한 작업을 다시 수행해야 함을 의미합니다.

첫 번째 부분 인 dropEvery은 다음과 같습니다. take 첫 번째 count-1 항목이 나머지 목록에서 가져온 항목과 연결됩니다.

그 후 drop count라고 말합니다. (N-1에 대해 잊어 버리고, N 번째 자리에서 1을 버려야합니다.) 그리고 이것들을 버린 후에는 같은 논리를 반복적으로 남은 부분에 적용합니다.

이런 방식으로 사용하면 Haskell에서 상당히 비쌀 수 있습니다. 따라서 성능 측면에서 볼 때 매우 좋지는 않지만 99 개 질문 페이지에서 사용할 수있는 짧은 구현 중 하나였습니다. 여기

좀 더 읽기 어쩌면 하나 샷에 모든 것을 할 수있는 기능입니다 :

byTwos :: [a] -> [(a,a)] 
byTwos [] = [] 
byTwos xs = zip firsts seconds 
    where enumerated = zip xs [1..] 
      firsts  = [fst x | x <- enumerated, odd $ snd x] 
      seconds = [fst x | x <- enumerated, even $ snd x] 

이 경우, 나는이 문제가있는 경우 zip으로 해결하기 쉬운 것입니다 말로 시작 I 홀수 색인 요소 목록과 짝수 색인 요소 목록이 이미 있습니다. 그럼 그냥 쓰고, where 절에 넣는 것에 대해 걱정하겠습니다.

where 절에서 먼저 zip xs [1..]을 말하면 [("Questions", 1), ("that", 2), ...]이됩니다.

사이드 노트 : fst은 튜플의 첫 번째 요소를 취하고 snd은 두 번째 요소를 사용합니다.

나서 firsts 번째 요소 홀수 경우 모든 값의 첫 번째 요소를 가지고 말한다 - 이들은 zip로부터 최종 출력 튜플의 "최초"로서 기능한다.

seconds 같은 일을 말한다 만 경우 두 번째 요소는 짝수 - 이러한 zip에서 최종 출력 튜플에 "초"로 될 것입니다.

목록이 홀수 길이 경우

, firsts 한 요소 이상 seconds보다 더 그래서 최종 zip 목록의 마지막 요소는 단순히 삭제됩니다 것을 의미 할 것이다, 그 결과 당신이 전화 것처럼 동일합니다 목록의 앞부분에있는 기능 (최종 요소를 제외한 모든 요소).

간단한 방법 (즉, 요소의 홀수 실패)에 대한
+0

의 요소가 짝수 일 수 있습니다. 그것이 나를 위해 정말로 혼란 스럽기 때문에 –

+0

대단히 감사합니다! –

+0

마지막 기능을 조금 자세히 설명해 주시겠습니까? 나는 당신이 그곳에서하고있는 것을 전적으로 얻었는지 확신하지 못합니다 ... –

3

당신은

combine :: [a] -> [(a, a)] 
combine (x1:x2:xs) = (x1,x2):combine xs 
combine (_:_) = error "Odd number of elements" 
combine [] = [] 

Live demo

을 사용할 수 있습니다 또는 당신은 내가 그렇지 않은 타 대답 같은 일부 복잡한 방법을 사용할 수 있습니다 정말로 이해하고 싶다.

더 일반적인 :

당신이 xs에 의해 이름이 주어진 목록 즉, 목록에있는 모든 두 개의 연속 된 항목을 페어링의 원하는 결과를 얻을 수 있습니다 Data.List.Split에서 chunk를 사용
map2 :: (a -> a -> b) -> [a] -> [b] 
map2 f (x1:x2:xs) = (f x1 x2) : map2 f xs 
map2 _ (_:_) = error "Odd number of elements" 
map2 _ [] = [] 
+0

재미있는 기능. 라이브 데모를 사용하여 –

+0

이것은 매우 간결한 반면, 홀수 길이 목록의 패턴 일치 오류가 나에게 너무 많은 고통을주기 때문에 명시 적으로 패턴 일치 'x : y : xs'를 피하는 것이 나의 목표 중 하나이며, 도우미 함수 그것을 피하는 것은 꽤 쉽습니다. – ely

+0

문제가 표시되지 않습니다. –

0

,

import Data.List.Split 

map (\ys -> (ys!!0, ys!!1)) $ chunk 2 xs 

이 솔루션은 주어진 목록에 짝수 개의 항목이 있다고 가정합니다.

f [] = [] 
f (x:y:xs) = (x,y):f(xs) 

그것은 빈리스트가 빈 목록을 제공한다는 것을 의미하고, 두 개 이상의 요소 목록이 두 몇 당신에게 목록을 반환 :

0

간단한 패턴 매칭 트릭을 할 수 다음 요소와 동일한 추론을 적용하면 ...

관련 문제