我需要過濾一組物件(已經按屬性 A 排序),洗掉屬性 B 無序的專案(下面用粗體標記):(為簡單起見,元組集)
情況1:
- 輸入序列((10, 10), (20, 20), (30, 36), (40, 30) , (50, 40), (60, 50))
- 預期輸出:Seq((10, 10), (20, 20), (30, 36), (50, 40), (60, 50))
- 實際輸出:Seq((10,10), (20,20), (40,30), (50,40))
案例2:
- 輸入:Seq((10, 10), (20, 20), (30, 36), (40, 40), (50, 30) , (60, 50))
- 預期輸出:Seq((10, 10), (20, 20), (30, 36), (40, 40), (60, 50))
- 實際輸出:Seq((10,10), (20,20), (30,36), (50,30))
我很感激任何幫助。
這是我到目前為止:
@RunWith(classOf[SpringRunner])
class OutOfOrderTest extends AnyWordSpec with Matchers with Debuggable {
"OutOfOrderTest" should {
def ooo(a: Seq[(Int, Int)]): Option[(Int, Int)] = {
val x = a.head
val y = a.tail.head
if (x._2 <= y._2) Some(x) else None
}
"filter out of order simple" in {
val bad = Seq((10, 10), (20, 20), (30, 36), (40, 30), (50, 40), (60, 50))
val filtered = bad.sliding(2).collect { a =>
ooo(a)
}.filter(_.isDefined).map(_.get).toSeq
filtered shouldEqual Seq((10, 10), (20, 20), (30, 36), (50, 40), (60, 50))
}
"filter out of order complex" in {
val bad2 = Seq((10, 10), (20, 20), (30, 36), (40, 40), (50, 30), (60, 50))
val filtered2 = bad2.sliding(2).collect { a =>
ooo(a)
}.filter(_.isDefined).map(_.get).toSeq
filtered2 shouldEqual Seq((10, 10), (20, 20), (30, 36), (40, 40), (60, 50))
}
}
}
更新 1
我使用序列來提高性能(可能最好使用陣列,但我可以稍后處理)
For simplicity I used Tuples here, but they are actually instances of a case class (Target) where 2 of the fields are represented by the tuple data.
Also this is one filter in a much bigger Spring-boot application, and I have to make a component out of it.
While there is no problem 'componentizing' (yes, we made that word up here in the office) the filter, the recursive function from @Luis will be hard to abstract as follows:
I'd like to test the three approaches as components So if I could I would mark the 3 answers as valid.
case class Target(rt: Double, ri: Double)
trait OutOfOrderRemover {
def filter(targets: Seq[Target])
}
@Component
class RecurtsiveOOO extends OutOfOrderRemover {
override def filter(targets: Seq[Target]): Seq[Target] = { }
}
uj5u.com熱心網友回復:
這是我的 2 美分。
這將為兩個發布的input示例回傳所需的結果。
input.head : input.sliding(2).collect{
case Seq((_,b1),(a2,b2)) if b1 <= b2 => (a2,b2)
}.toSeq
警告:如果input為空將拋出。
uj5u.com熱心網友回復:
恕我直言,這是尾遞回的完美用例。
def removeUnsortedElements[A, B](data: List[A])(orderBy: A => B)(implicit ev: Ordering[B]): List[A] = {
import Ordering.Implicits._
@annotation.tailrec
def loop(remaining: List[A], previous: B, acc: List[A]): List[A] =
remaining match {
case a :: tail =>
val next = orderBy(a)
val newAcc =
if (next >= previous) a :: acc
else acc
loop(
remaining = tail,
previous = next,
acc = newAcc
)
case Nil =>
acc.reverse
}
data match {
case first :: tail =>
loop(
remaining = tail,
previous = orderBy(first),
acc = first :: Nil
)
case Nil =>
Nil
}
}
可以這樣使用:
val input1 = List((10, 10), (20, 20), (30, 36), (40, 30), (50, 40), (60, 50))
val output1 = removeUnsortedElements(input1)(_._2)
// output1: List[Int] = List((10,10), (20,20), (30,36), (50,40), (60,50))
val input2 = List((10, 10), (20, 20), (30, 36), (40, 40), (50, 30), (60, 50))
val output2 = removeUnsortedElements(input2)(_._2)
// output2: List[Int] = List((10,10), (20,20), (30,36), (40,40), (60,50))
您可以在此處看到運行的代碼。
uj5u.com熱心網友回復:
您可以使用foldLeft空集合累加器,將當前值與累加器頭 1 進行比較,如果滿足條件,則附加當前值,然后反轉結果:
val bad = ...
val filtered = bad.foldLeft(List.empty[(Int, Int)])((acc, t) => acc match {
case head :: _ if head._2 > t._2 => acc
case _ => t :: acc
})
.reverse
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/312798.html
標籤:spring-boot scala filtering scala-collections
