scala / scala-library-next

backwards-binary-compatible Scala standard library additions
Apache License 2.0
69 stars 17 forks source link

Strict version of `Map.filterKeys` #176

Open OndrejSpanel opened 7 months ago

OndrejSpanel commented 7 months ago

Map.filterKeys is deprecated as the moment. Its deprecation message says:

Use .view.filterKeys(f). A future version will include a strict version of this method (for now, .view.filterKeys(p).toMap).

The suggested .view.filterKeys(p).toMap is not very efficient, it rebuilds the whole map. Could a strict version be added as promised by the deprecation warning?

Following workaround provides a more efficient solution for those interested:

  implicit class MoreMapOps[K, V](private val m: Map[K, V]) extends AnyVal {
    def filterKeysStrict(predicate: K => Boolean): Map[K, V] = {
      m.removedAll(m.keys.filterNot(predicate))
    }
  }

See also https://stackoverflow.com/q/78354572/16673

OndrejSpanel commented 7 months ago

The mapValues has the same promise in its deprecation and suffers the same performance issue. I did not need it yet, but I guess it should be added for completeness:

Use .view.mapValues(f). A future version will include a strict version of this method (for now, .view.mapValues(f).toMap).

BalmungSan commented 7 months ago

Note that @OndrejSpanel you don't want the strict version IIUC, since that is what m.view.filterKeys(p).toMap does; that strict version is mostly to reduce the boilerplate.

Rather, it seems you want a lazy version that behaves like m.view.filterKeys but without loosing the Map type.

OndrejSpanel commented 7 months ago

Rather, it seems you want a lazy version that behaves like m.view.filterKeys but without loosing the Map type.

Is that even possible? And if it is, I find it hard to believe any lazy solution would work well when chained multiple times, which is what my use case really is - like (((map.filterKeys(p1) ++ aSeq1).filterKeys(p2) ++ aSeq2) ... .filterKeys(pN)) ++ aSeqN

Maybe what I really want is my workaround and I do not need this API at all. Maybe it is not possible to be more efficient?