Ophelia - 1 year ago 74
Scala Question

# Scala sort one list according to the values in another one

I have two IndexedSeq

``````works[Work]
order[Int]
``````

Each object Work has an id field with integer value: Work.id
In order lists there are ids, which are in the order we need to sort out the work. Like, in position 0 there is a first id, so we need to find the work in the works array with id that corresponds this one, and put it in the 0 place and so on.
Is there any way to do this with scala without going through two loops?Like, some elegant way?
Some pseudo data, for example:

``````order = 33, 22, 11, 55

works = (33, "some text"), (55, "eeeee"), (22, "fdsfs"), (11, "fdsffds")
``````

After the sorting:

``````order = 33, 22, 11, 55

works = (33, "some text"),(22, "fdsfs"),  (11, "fdsffds"), (55, "eeeee"),
``````

You may use dictionary for that, the complexity is O(N) here (which is better in comparision with N*N for two nested cycles):

``````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))
``````

if your entities is something more than tuples:

``````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))
``````

if you don't want to spent a memory for `Map` - just use find instead of `Map.apply` (but it would be O(N*N), so it's slower):

``````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))
``````

If you don't want to have an exception in case if `order` doesn't contain your key, you may use `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))
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download