2013-11-11 3 views
1

Пожалуйста, извините за мой английский :( Поясним мой вопрос на примерах У нас есть массив a:.Scala. Аргументы вложенными лямбды с коротким синтаксисом

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

Мы можем:

  1. фильтр a :

    a.filter(_ < 2) 
    
  2. Подсчитайте несколько элементов в:

    a.count (_ < 2) 
    
  3. Получение уникальных элементов в коллекции:

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

Вопрос заключается в: как сделать третий пункт, но без введения переменной я? Можно ли написать что-то вроде:

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

Я понимаю, что я могу написать это (и это еще не хватает):

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

Но я просто заинтересован в ответе.

ответ

4

Вы не можете сделать это без введения переменной i, потому что для этого требуются переменные смешивания из двух разных областей (так называемый closure). Если мы напишем это без использования переменной-заполнителя _, это станет более понятным.

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

Для каждого значения outer в a, мы создаем новую функцию, чтобы пройти к count, в котором outer постоянна и inner передается в качестве параметра. _ может действовать только как заполнитель для самой внутренней функции, в которой он используется, и поэтому не может использоваться для замены outer. Вот почему

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

компилирует но

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

нет.

0

Упомянет альтернативное решение (не простое, но быстрее, я полагаю)

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

или 'хз группеГо тождества собирающего {случай (k, v), если V.SIZE == 1 => к}' – sschaef

+1

Или (еще быстрее и сложнее): 'a.foldLeft (collection.mutable.Map [Any, Int](). WithDefaultValue (0)) ((m, x) => {m (x) + = 1; m}). filter (_._ 2 == 1) .keys'. Правда, только быстрее для списков из 70 или более элементов. – colevk

Смежные вопросы