Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MapFactory.iterate #126

Open
Lasering opened this issue Jul 28, 2022 · 4 comments
Open

MapFactory.iterate #126

Lasering opened this issue Jul 28, 2022 · 4 comments

Comments

@Lasering
Copy link

Lasering commented Jul 28, 2022

I'm constantly doing (or variations of):

list.map { a =>
  val value = //some code to compute the value, mostly likely using `a`
  a.name -> value
}.toMap

Which is annoying since I'm allocating an intermediate list when I would prefer to build the map directly.

A method like this could be added to MapFactory:

import scala.collection.MapFactory
extension [CC[_, _]](factory: MapFactory[CC])
  def iterate[A, K, V](iterable: IterableOnce[A])(f: A => (K, V)): CC[K, V] =
    val builder = factory.newBuilder[K, V]
    iterable.iterator.foreach(a => builder.addOne(f(a)))
    builder.result()

(Feel free to bike shed the names/implementation)

Currently IterableFactory has some very good utility methods to construct iterables such as fill, iterate, range, and tabulate. MapFactory on the other hand has nothing.

@Lasering
Copy link
Author

Lasering commented Jan 10, 2023

These methods are more difficult to argue for their inclusion but they are still useful (names could be improved):

extension [CC[_, _]](factory: MapFactory[CC])
  def iterateKey[A, K](iterable: IterableOnce[A])(key: A => K): CC[K, A] =
    iterate(iterable)(e => (key(e), e))
  def iterateValue[A, V](iterable: IterableOnce[A])(value: A => V): CC[A, V] =
    iterate(iterable)(e => (e, value(e)))

@OndrejSpanel
Copy link
Member

You can use view to avoid intermediate collection:

list.view.map { a =>
  val value = //some code to compute the value, mostly likely using `a`
  a.name -> value
}.toMap

Does this have some drawbacks for you?

@Lasering
Copy link
Author

Does this have some drawbacks for you?

In terms of performance no, but in terms of readability and consistency with the IterableFactory yes. I find it easier to read:

Map.iterate { a =>
  val value = //some code to compute the value, mostly likely using `a`
  a.name -> value
}

Mainly because the intention of creating a map is in the beginning of the code, and the cognitive load of reading the code is smaller.

@jozic
Copy link

jozic commented Jan 12, 2023

Those are indeed very handy. I've added those to my small homegrown lib.

https://github.com/jozic/scalax-collection#maptomap

https://github.com/jozic/scalax-collection#tomapwithkey

https://github.com/jozic/scalax-collection#tomapwithvalue

But if they appear in this lib, i will happily switch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants