10

The standard library offers the unzip method on List:


scala>val l = List((1, "one"), (2, "two"), (3, "three"), (4, "four"), (5, "five"))

scala> l.unzip
// res13: (List[Int], List[String]) = (
//  List(1, 2, 3, 4, 5),
//  List("one", "two", "three", "four", "five")
//)

Is there a way to achieve the same on NonEmptyList from the cats library:

scala> import cats.data.NonEmptyList

scala> val nel = NonEmptyList.of((1, "one"), (2, "two"), (3, "three"), (4, "four"), (5, "five"))
//res15: NonEmptyList[(Int, String)] = NonEmptyList(
//  (1, "one"),
//  List((2, "two"), (3, "three"), (4, "four"), (5, "five"))
//)
Valy Dia
  • 2,781
  • 2
  • 12
  • 32

3 Answers3

5

You could simply call nel.toList and use the standard l.unzip and then NonEmptyList.fromList(unziped_list) on the result.

Edit: As @Dylan said, you could also use .fromListUnsafe to get rid of the option.

Arnaud Claudel
  • 3,000
  • 19
  • 25
  • +1 but I'd recommend using `.fromListUnsafe` at the end, since `.fromList` gets you an option, and since your result list is guaranteed to have come from a non-empty List, the "unsafe" method is safe to use. – Dylan Jul 18 '19 at 17:10
  • @Dylan: Calling `.fromListUnsafe` is used instead of just calling `.get` on the resulting option? – Ellesedil Jul 18 '19 at 17:28
  • @Ellesedil basically yes. [See for yourself](https://github.com/typelevel/cats/blob/master/core/src/main/scala/cats/data/NonEmptyList.scala#L458) – Dylan Jul 18 '19 at 17:33
2

The unzip method is available for NonEmptyList if you import cats.syntax.functor._.

scala> import cats.data.NonEmptyList
                                                                             
scala> import cats.syntax.functor._
                                                                             
scala> val nel = NonEmptyList.of((1, "one"), (2, "two"), (3, "three"), (4, "four"))
val nel: cats.data.NonEmptyList[(Int, String)] = NonEmptyList((1,one), (2,two), (3,three), (4,four))
                                                                             
scala> nel.unzip
val res0: (cats.data.NonEmptyList[Int], cats.data.NonEmptyList[String]) = (NonEmptyList(1, 2, 3, 4),NonEmptyList(one, two, three, four))
rrramiro
  • 21
  • 3
1

You don't have to do it all in one traversal, and often you don't even want to use one of the parts. I would write it like:

(nel.map(_._1), nel.map(_._2))

This avoids the awkward conversion away from an NEL and back.

Karl Bielefeldt
  • 47,314
  • 10
  • 60
  • 94