2017-06-23 17 views
5

Jest snipt kod w kodzie Kotlin:nawrócony komparator lambda w Kotlin

val dataMap = sensoryDataUsage.groupBy { it } 
     .mapValues { it.value.count().toDouble()/count } 
     .mapKeys { println(it.key); it.key.toDouble()/max } 
     .toSortedMap(object : Comparator<Double> { 
      override fun compare(p0: Double, p1: Double): Int { 
       return (p1-p0).compareTo(0) 
      } 
     }) 

To działało w porządku. Jednak IDE wciąż sugeruje mi przekonwertować ten obiekt komparatora do lambda, i nie tylko, że:

val dataMap = sensoryDataUsage.groupBy { it } 
     .mapValues { it.value.count().toDouble()/count } 
     .mapKeys { println(it.key); it.key.toDouble()/max } 
     .toSortedMap {x, y -> (y-x).compareTo(0)} 

Ta praca shold. Jednak nie można go skompilować:

Error:(32, 14) Kotlin: Type inference failed: fun <K, V> Map<out K, V>.toSortedMap(comparator: Comparator<in K>): SortedMap<K, V> cannot be applied to receiver: Map<Double, Double> arguments: ((Double, Double) -> Int) 

Jakieś pomysły, co poszło nie tak? Z góry dziękuję.

+0

Czy przekształcić go ręcznie lub zastosować zamiar dostarczonego przez IDE? – Ilya

Odpowiedz

6

Spróbuj w ten sposób:

val dataMap = sensoryDataUsage.groupBy { it } 
     .mapValues { it.value.count().toDouble()/count } 
     .mapKeys { println(it.key); it.key.toDouble()/max } 
     .toSortedMap(Comparator<Double> { p0, p1 -> (p1-p0).compareTo(0) }) 

masz wiele odpowiedzi z kodem pracy, ale postaram się wyjaśnić, dlaczego nie zrobił praca kod. Spójrz na ten lambda:

p0, p1 -> (p1-p0).compareTo(0) 

Byłoby wygenerować metodę, która zwraca jeden określony typ środka ostatniego zwanej metody, w naszym przypadku - compareTo. Innymi słowy - ta wartość lambda zwróci liczbę całkowitą. Ale twój kod wymaga podwójnego, więc powinieneś określić rodzaj zwracanej wartości jako Double. Teraz, gdy masz powody, możesz skorzystać z któregoś z sugerowanych rozwiązań, który pasuje ci lepiej.

+1

Dziękuję za odpowiedź, ale nie rozumiem. Powiedziałeś, że "ten lambda zwróci liczbę całkowitą, ale twój kod wymaga podwójnego", jednak metoda compareTo Komparatora musi zwracać wartość int, a nie Double. Bardziej do rzeczy, jeśli zamieniam lambdę na "p0, p1 -> 0.0" to nadal nie działa pomimo zwrócenia podwójnego. O ile mogę powiedzieć, to dlatego, że kompilator nie może wywnioskować typów p0 i p1, ale nie wiem dlaczego (co ciekawe, może wywnioskować typy w przypadku Collections.sort (...)). – TheIT

+1

@TheIT, w rzeczywistości masz rację, nie może on dziedziczyć typu i nie mogę również powiedzieć, dlaczego mógł on zostać odziedziczony po 'Collections.sort' i nie można go tutaj zrobić. Hmm, przepraszam, myślałem, że compareTo zwraca wartość z typem danych wejściowych. Daj mi znać o twoim śledztwie, może uda nam się poprawić i ukończyć tę odpowiedź –

3

Twój kod powinien wyglądać następująco:

val dataMap = sensoryDataUsage.groupBy { it } 
    .mapValues { it.value.count().toDouble()/count } 
    .mapKeys { println(it.key); it.key.toDouble()/max } 
    .toSortedMap(Comparator<Double>{x, y -> (y-x).compareTo(0)}); 

LUB można usunąć wyraz y-x:

val dataMap = sensoryDataUsage.groupBy { it } 
    .mapValues { it.value.count().toDouble()/count } 
    .mapKeys { println(it.key); it.key.toDouble()/max } 
    .toSortedMap(Comparator<Double>{x, y -> y.compareTo(x)}); 

LUB korzystając compareByDescending Zamiast:

val dataMap = sensoryDataUsage.groupBy { it } 
    .mapValues { it.value.count().toDouble()/count } 
    .mapKeys { println(it.key); it.key.toDouble()/max } 
    .toSortedMap(compareByDescending{ it }); 
+0

lub możesz użyć Komparatora , aby określić typ powrotu lambda. –

0

Wymień

.toSortedMap {x, y -> (y-x).compareTo(0)} 

z

.toSortedMap {x:Double, y:Double -> (y-x).compareTo(0)}