Scala的排序一个列表,根据在另一个
值我有两个IndexedSeqScala的排序一个列表,根据在另一个
works[Work]
order[Int]
每个对象工作具有整数值的id字段:Work.id 为了列出有IDS,这是在我们需要整理工作的顺序。就像在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"),
您可以使用字典的是,复杂度为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
- 只用找到的,而不是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))
如果你不“T希望在情况异常,如果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))
我真的很喜欢第二张照片的样子,让我测试一下:) – Ophelia 2015-04-02 16:29:57
你可能会感兴趣的sortWith
方法:
works.sortWith((a, b) => order.indexOf(a._1) < order.indexOf(b._1))
假设你有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))
现在你可以租期,提高通过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)。
您可以从地图上以相同的顺序为Seq[WorkId]
转换Seq[Work]
为Map[WorkId, Work]
和collect
值。
例如:
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"))
这实际上应该被标记为正确的答案,它超级简单,工作得很好。 – OOPMan 2016-11-08 19:01:49
邮编在一起,排序,然后再解压? – 2015-04-02 16:07:11
听起来奇怪0_o这是如何工作的,究竟是什么? – Ophelia 2015-04-02 16:08:33
当然有一种方法。发布'IndexedSeq''works'和'orders'的样本数据以及您希望输出的样子。 – Brian 2015-04-02 16:08:57