2011-12-04 7 views
1
let standard = (0, 4.5M, 4L) 
let tuples = [| ("A", -2, 1.0M, 2L); 
       ("B", -1, 2.0M, 3L); 
       ("C", 0, 3.0M, 4L); 
       ("D", 1, 4.0M, 5L); 
       ("E", 2, 5.0M, 6L) |] 
let qualified = tuples 
       |> Array.sortBy(fun (_, a, b, c) -> (a, -b, c)) 
       |> Array.filter(fun (_, a, b, c) -> (a, b, c) <= standard) 
printfn "%A" qualified 

나는 튜플 배열과 표준을 가지고 있습니다. 튜플을 정렬하고 요구 사항을 충족하는 튜플을 선택하고 싶습니다.
튜플의 경우 첫 번째 요소를 무시하고 두 번째 요소와 네 번째 요소를 일반적인 방식으로 정렬하지만 세 번째 요소를 역순으로 정렬합니다. 두 번째 요소가있는 모든 튜플은 표준보다 크고 세 번째 요소는 표준 튜플만큼 큰 것이므로 표준 튜플을 사용합니다. 위의 예에서 정규화 된 튜플은 = [| 조건 : 두 번째 요소> = 0이고 세 번째 요소 < = 4.5M 및 네 번째 요소> = 4L 하지만 내 코드가 작동하지 않았습니다! 기능을 작성하는 방법을 알려 주시면이 작업을 수행 할 수 있습니다! 감사합니다. 좋은 주말 보내세요. 존F # 튜플 배열 정렬

+0

어떤 방식으로 d 이드는 코드 "작동하지 않는다"? – Richard

답변

3

난 당신이이 튜플에서 작동 비해 내장 사용하여 원하는 일을 할 수있는 현명한 방법이라고 생각하지 않습니다. 가장 큰 문제는 첫 번째 요소를 가장 중요한 것으로서 비교하기 때문에 나머지 요소를 고려하지 않고 처음 몇 요소 만 사용한다는 것입니다. 조건에 따라 모두 요소에 대한 제한이 지정됩니다. 따라서 Gustavo 아마 갈 수있는 가장 쉬운 방법입니다

그러나, 약간의 지점이 - 첫째, 필터링을 수행하는 것이 좋습니다 수 있습니다 정렬 전에, 다음 정렬 기능이 적은 요소를 정렬 할 필요가 있기 때문이다. :

let qualified = 
    tuples 
    |> Array.sortBy (...) 
    |> Array.filter (...) 

조건을 변경하기 쉬운 전역 값으로 표현하기를 원한다. 값이 최소값인지 최대 값인지를 말하지 않기 때문에 필요한 최소값/최대 값을 지정하는 3 개의 값을 갖는 튜플을 생성하는 것은 충분하지 않다. 하면 조건 지정 기능 튜플 사용할 수 :

let standard = ((fun _ -> true), (<=) 0, (>=) 4.5M, (<=) 4L) 

이 첫 번째 요소의 모든 값이 OK임을 지정 번째 요소의 값 x를 취하는 함수보다 큰 영 ((<=) 0 스탠드되어야 0 <= x을 반환합니다. 다음은 다음과 같이 쓸 수 있습니다.

let conditionsHold (p1, p2, p3, p4) (v1, v2, v3, v4) = 
    p1 v1 && p2 v2 && p3 v3 && p4 v4 

let qualified = 
    tuples 
    |> Array.sortBy(fun (_, a, b, c) -> (a, -b, c)) 
    |> Array.filter (conditionsHold standard) 
+0

안녕하세요, 토마스 : 훌륭한 코드와 자세한 설명을 보내 주셔서 감사합니다. 코드에 사소한 문제가 발생했습니다. 정렬하기 전에 필터를 두는 것이 좋습니다! 큰 도움을 주셔서 다시 한 번 감사드립니다. 존 –

2

는 단지의 마지막 줄을 변경 : 튜플 ("D", 1, 4.0M, 5L)도 자격이 있음을

Array.filter(fun (_, a, b, c) -> let (x,y,z) = standard in a >= x && b <= y && c >= z) 

참고.

UPDATE :

토마스 처음 필터링하는 것이 좋습니다, 권리입니다. 문제를 해결하는 또 다른 흥미로운 기능적 방법으로 3-uple을 적용 할 수있는 함수 작성자로 만들 수 있습니다.

let pure' x = (x,x,x) 
let (<*>) (f,g,h) (x,y,z) = (f x, g y, h z) 

let standard = (0, 4.5M, 4L) 
let tuples = [| ("A", -2, 1.0M, 2L); 
       ("B", -1, 2.0M, 3L); 
       ("C", 0, 3.0M, 4L); 
       ("D", 1, 4.0M, 5L); 
       ("E", 2, 5.0M, 6L) |] 
let qualified = tuples    
       |> Array.filter(fun (_, a, b, c) -> ((>=),(<=),(>=)) <*> (a,b,c) <*> standard = pure' true) 
       |> Array.sortBy(fun (_, a, b, c) -> (a, -b, c)) 
+0

대단히 감사합니다. 그러나 다른 방법을 생각하고 있습니다 : 튜플의 배열에 세 번째 요소 앞에 음수를 넣은 다음 튜플 배열을 정렬 한 다음 표준 튜플과 비교하면 올바른 결과가 나올 수 있지만 몇 가지 테스트를 해보십시오. 다시 코드를 보내 주셔서 감사합니다! –

+0

@Gustavo - 응용 펑터를 사용하는 것은 흥미로운 가능성이지만, 나는 정당한 이유없이 코드를 지나치게 복잡하게 만들고 있다고 생각합니다. 내 버전조차도 불필요하게 복잡 할 수도 있지만, 최소한 응용 펑터와 같은 멋진 개념을 소개 할 필요는 없다고 생각합니다. (즉, F #이 맹목적으로 하스켈 패턴을 채택해서는 안된다고 생각합니다.) –

+0

@Tomas - 아마 맞을 것입니다. 이 경우 너무 많을 수 있습니다. 필자는 개인적으로 응용 펑터의 가독성을 좋아하고 다른 대안을 보여주고 싶었습니다. – Gustavo