3

Please, sorry for my English :( Let's explain my question by examples. We have an array a:

    var a = Array(1,1,1,1,2)

We can:

  1. filter a:

    a.filter( _ < 2 )
    
  2. Count some elements in a:

    a.count (_ < 2)
    
  3. Getting unique elements in the collection:

    a.filter { i =>
        a.count(_ == i) == 1
    }
    

The question is: how to do third clause but without introducing variable i? Is it possible to write something like:

    a.filter ( a.count ( _ == __) == 1 )

I understand that I can write this (and it's still short):

    a.filter { i => a.count(_ == i) == 1 }

But I'm just interested in the answer.

2 Answers 2

5

You can't do this without introducing the variable i because it requires mixing variables from two different scopes (what is known as a closure). If we write this without using the _ placeholder variable, this becomes clearer.

a.filter( outer =>
  a.count( inner =>
    outer == inner
  ) == 1
)

For every value of outer in a, we are creating a new function to pass to count, in which outer is constant and inner is passed in as a parameter. _ can only act as a placeholder for the innermost function it is used in, and so can't be used to replace outer. This is why

a.filter( outer =>
  a.count(
    outer == _
  ) == 1
)

compiles but

a.filter(
  a.count( inner =>
    _ == inner
  ) == 1
)

does not.

Sign up to request clarification or add additional context in comments.

Comments

0

Just to mention an alternate solution (not simpler, but faster I suppose)

a.groupBy(identity).filter{ case (_, v) => v.size == 1}.keys

2 Comments

or xs groupBy identity collect { case (k, v) if v.size == 1 => k }
Or (even faster and more complex): a.foldLeft(collection.mutable.Map[Any, Int]().withDefaultValue(0))((m, x) => { m(x) += 1; m }).filter(_._2 == 1).keys. Really only faster for lists of 70 or more elements, though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.