我有两个IndexedSeq
works[Work]
order[Int]
每个对象Work都有一个带整数值的id字段:Work.id 在订单列表中有一些ID,它们按照我们需要整理工作的顺序排列。就像,在位置0中有第一个id,所以我们需要在工作数组中找到与此对应的id的工作,并将其放在0位置,依此类推。 有没有办法用scala做这个而不经过两个循环?就像,一些优雅的方式? 一些伪数据,例如:
order = 33, 22, 11, 55
works = (33, "some text"), (55, "eeeee"), (22, "fdsfs"), (11, "fdsffds")
排序后:
order = 33, 22, 11, 55
works = (33, "some text"),(22, "fdsfs"), (11, "fdsffds"), (55, "eeeee"),
答案 0 :(得分:7)
你可以使用字典,这里的复杂度是O(N)(两个嵌套循环的N * N比较好):
scala> val order = List(33, 22, 11, 55)
order: List[Int] = List(33, 22, 11, 55)
scala> val works = List((33, "some text"), (55, "eeeee"), (22, "fdsfs"), (11, "fdsffds"))
works: List[(Int, String)] = List((33,some text), (55,eeeee), (22,fdsfs), (11,fdsffds))
scala> val worksMap = works.toMap
worksMap: scala.collection.immutable.Map[Int,String] = Map(33 -> some text, 55 -> eeeee, 22 -> fdsfs, 11 -> fdsffds)
scala> val newWorks = order zip order.map(worksMap)
newWorks: List[(Int, String)] = List((33,some text), (22,fdsfs), (11,fdsffds), (55,eeeee))
如果您的实体不仅仅是元组:
scala> val worksMap = (works map (_._1) zip works).toMap //any other key extraction, like `_.myKey` may be applied instead of `_._1`
worksMap: scala.collection.immutable.Map[Int,(Int, String)] = Map(33 -> (33,some text), 55 -> (55,eeeee), 22 -> (22,fdsfs), 11 -> (11,fdsffds))
scala> order.map(worksMap)
res13: List[(Int, String)] = List((33,some text), (22,fdsfs), (11,fdsffds), (55,eeeee))
如果你不想花费Map
的内存 - 只需使用find而不是Map.apply
(但它会是O(N * N),所以它是较慢):
scala> val newWorks = order.map(x => works.find(_._1 == x).get)
newWorks: List[(Int, String)] = List((33,some text), (22,fdsfs), (11,fdsffds), (55,eeeee))
如果order
不包含您的密钥,如果您不想要例外,则可以使用flatMap
:
scala> val newWorks = order.flatMap(x => works.find(_._1 == x))
newWorks: List[(Int, String)] = List((33,some text), (22,fdsfs), (11,fdsffds), (55,eeeee))
scala> order.flatMap(worksMap.get)
res15: List[(Int, String)] = List((33,some text), (22,fdsfs), (11,fdsffds), (55,eeeee))
答案 1 :(得分:5)
您可能对sortWith
方法感兴趣:
works.sortWith((a, b) => order.indexOf(a._1) < order.indexOf(b._1))
答案 2 :(得分:3)
您可以按照与Seq[Work]
相同的顺序将Map[WorkId, Work]
转换为collect
和Seq[WorkId]
地图中的值。
例如:
case class Work(id: Int, text: String)
// defined class Work
val order = Seq(33, 22, 11, 55)
// order: Seq[Int] = List(33, 22, 11, 55)
val works = Seq(Work(33, "some text"), Work(55, "eeeee"), Work(22, "fdsfs"), Work(11, "fdsffds"))
// works: Seq[Work] = List(Work(33, "some text"), Work(55, "eeeee"), Work(22, "fdsfs"), Work(11, "fdsffds"))
val workMap = works.map(work => work.id -> work).toMap
// workMap: Map[Int, Work] = Map(33 -> Work(33, "some text"), 55 -> Work(55, "eeeee"), 22 -> Work(22, "fdsfs"), 11 -> Work(11, "fdsffds"))
order.collect(workMap)
// res14: Seq[Work] = List(Work(33, "some text"), Work(22, "fdsfs"), Work(11, "fdsffds"), Work(55, "eeeee"))
这与其他答案类似,但使用的是collect
,因为Map[A, B]
也是PartialFunction[A, B]
。
但是,上述解决方案假设工作ID是唯一的。
如果工作ID不是唯一的,您可以使用groupBy
和flatMap
:
val works = Seq(Work(33, "a"), Work(34, "b"), Work(33, "c"), Work(35, "d"))
// works: Seq[Work] = List(Work(33, "a"), Work(34, "b"), Work(33, "c"), Work(35, "d"))
val worksMap = works.groupBy(_.id)
//worksMap: Map[Int, Seq[Work]] = Map(35 -> List(Work(35, "d")), 34 -> List(Work(34, "b")), 33 -> List(Work(33, "a"), Work(33, "c")))
val order = Seq(35, 34, 33)
//order: Seq[Int] = List(35, 34, 33)
order.flatMap(id => worksMap.getOrElse(id, Seq.empty))
// res23: Seq[Work] = List(Work(35, "d"), Work(34, "b"), Work(33, "a"), Work(33, "c"))
答案 3 :(得分:2)
假设您的数据位于List
,您可以执行以下操作:
scala> val order = List(33, 22, 11, 55)
order: List[Int] = List(33, 22, 11, 55)
scala> val works = List((33, "some text"), (55, "eeeee"), (22, "fdsfs"), (11, "fdsffds"))
works: List[(Int, String)] = List((33,some text), (55,eeeee), (22,fdsfs), (11,fdsffds))
scala> val sortedWorks = order.flatMap( id => works.find(x => x._1 == id ))
sortedWorks: List[(Int, String)] = List((33,some text), (22,fdsfs), (11,fdsffds), (55,eeeee))
现在你可以使用Map来优化按ID查找工作的部分,这样就可以了:
scala> val worksMap = works.toMap
worksMap: scala.collection.immutable.Map[Int,String] = Map(33 -> some text, 55 -> eeeee, 22 -> fdsfs, 11 -> fdsffds)
scala> val sortedWorks = order.flatMap( id => worksMap.get(id))
sortedWorks: List[String] = List(some text, fdsfs, fdsffds, eeeee)
性能取决于查找。在这种情况下,由于HashMap,它是摊销的O(N)。