2013-03-05 6 views
0

우아한 Scala 솔루션을 사용하면 어떤 조건 그룹과도 일치하는 요소를 찾을 수 있지만 각 조건마다 다른 우선 순위가 있습니까? 다른 우선 순위 조건에 따라 요소를 찾는 방법은 무엇입니까?

case class A(p1:Int, p2:Int) 

List(A(2,3), A(4,4), A(3,5)) 

내가 쿼리 할 말 : 당신이하지 을 할 경우, 그것을 발견하는 항목이 p1 == p2을 찾을 당신이 그것을 찾을 수없는 경우, 등등 p1 = square(p2) 및 제공, p2 > p1 저에게 항목을 제공합니다. 항상 => Bool

첫 번째 추측은 각 루프마다 하나의 조건을 시도하는 재귀 찾기 기능이지만, 더 나은/간단한 방법이 있는지 알고 싶습니다.

이상적으로 항목이 더 많은 조건과 일치하면 선택되어야하지만 조건의 우선 순위는 여전히 준수해야합니다.

+1

collectFirst 할 수 있습니까? http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.List – smk

+0

항상 가장 큰 p2를 가진 항목을 찾을 수 있습니다. – Felix

+0

collectFirst처럼 보입니다. –

답변

6
l.find{x => x.p1 == x.p2}.getOrElse(l.maxBy(_.p2)) 

UPDATE : 당신은 "당신이 그것을 찾을 수없는 경우, 등등 가장 낮은 P1과를 제공, 가장 큰 P2와 나에게 아이템을 준다"라고 업데이트 된 질문에. 그러나 정의 상으로는 항상 가장 큰 가치가 있습니다 (목록이 비어 있지 않은 한 목록이 비어있을 수는 없지만). 그래서 이것은 실제로 "가장 큰 p2를 가진 아이템을주세요"(그러므로 위의 해결책)입니다.

UPDATE 2 : 질문이 다시 변경되어 "찾지 못하면 p1 == p2, 찾지 못하면 p2> p1로 항목을 제공하십시오. 찾지 못하면 그것, p1 = square (p2) 등등을 줘. " 결국 제네릭 솔루션이 필요하다고 생각합니다. 없음 요소가 어떤 조건에 일치하지 않는 경우 일부 (0)이 마지막 조건에 일치하는 경우, 일부 (1) :

// The list of predicates, in order of priority 
// (you can add/remove predicates as you see fit) 
val predicates = List[A => Boolean]( 
    x => x.p1 == x.p2, 
    x => x.p2 > x.p1, 
    x => x.p1 == x.p2*x.p2 
) 

val indexedPredicates = predicates.reverse.zipWithIndex 
def score(x: A): Option[Int] = indexedPredicates.find(_._1(x)).map(_._2) 
def priorityFind(l: List[A]): A = l.maxBy(score) 

아이디어는 각 요소에 점수를 속성 없다는 것입니다 : 그래서 여기에 필자의 마지막으로 하나의 술어와 일치하는 경우 등등. 그런 다음 가장 높은 점수 (None은 어떤 Some 인스턴스보다 "작음"이므로 가장 바람직한 점수를 얻습니다). 제대로 어떤 요소가 어떤 조건에 일치하지 않는 경우를 처리하려면

,이 같은 priorityFind을 바꿀 것 :

def priorityFind(l: List[A]): Option[A] = { 
    val filtered = l.view.flatMap{x => score(x).map(x -> _) } 
    if (filtered.isEmpty) None 
    else Some(filtered.maxBy(_._2)._1) 
} 
+2

나는 매우 우아한 maxBy에 대해 몰랐습니다 – maxmc

+0

질문에 대한 두 번째 업데이트를 해결하기 위해 제 솔루션을 일반적인 해결책으로 업데이트했습니다. 바라건대 이제 우리는 휴식을 취할 수 있습니다. –

+0

변경 사항에 대해 죄송합니다. 처음 발표했을 때 명확하지 않았습니다. –

1
list.find(i => i.p1 == i.p2).getOrElse(list.sortBy(-_.p2).head) 

업데이트, 당신의 새로운 요구 사항에 적합해야한다.

list.find(i => i.p1 == i.p2).getOrElse(
    list.find(i => i.p2 > i.p1).getOrElse(
    list.find(i => i.p1 == i.p2 * i.p2))) 
0

좋아, 나는이 함께했다 : 이제

case class A(p1:Int, p2:Int) 
val list = List(A(3,2), A(4,4), A(10,2), A(4,2)) 
val filter:PartialFunction[A,A] = { 
    case [email protected](p1,p2) if p1==p2 => a 
    case [email protected](p1,p2) if p2>p1 => a 
    case [email protected](p1,p2) if p1==p2*p2 => a 
} 

list.collect(filter).foreach(println) 

, 가장 적합한 것을 필요로한다면, 대신에 A => Int를 맵핑 한 다음 순위를 지정하는 순위 지정 함수를 작성합니다. 먼저 필터링 한 다음 나중에 순위별로 정렬하여 일부 작업을 저장할 수 있습니다. (수집에는 list.size 시간이 소요되는 반면 평균은 list.size * log (list.size)입니다.

관련 문제