2015-08-26 8 views
16

Mam List[Int] w Scala. Lista to List(1,2,3,4,5,6,7,8,9,10). Chcę, aby filter lista tak, że ma tylko numery parzyste. I chcę zmiksować liczby z 2. Czy to możliwe?Jak połączyć filtr i mapę w scala?

Mam nadzieję, że wyjaśniłem dokładnie to pytanie. Jeśli masz jakieś pytania, proszę zapytaj. Z góry dziękuję.

+2

Spróbuj użyć polecenia 'collect', łączy cechy" filtru "i" mapy ". – cmbaxter

+0

Patrzę teraz na to. Czy możesz podać przykład? Dokumentacja mówi o "częściowej funkcji" i nie wiem, co to znaczy. –

+0

Funkcja częściowa oznacza funkcję zdefiniowaną tylko w podzbiorze wszystkich możliwych wejść, która nie zwróci żadnego wyniku, gdy wejście znajduje się poza tym podzbiorem. Zobacz tutaj więcej: http://alvinalexander.com/scala/how-to-define-use-partial-functions-in-scala-syntax-examples – BlueSky

Odpowiedz

31

Jak stwierdza w swoim komentarzu, collect powinien robić to, co chcesz:

list.collect{ 
    case x if x % 2 == 0 => x*2 
} 

Sposób collect pozwala zarówno określić kryteria dotyczące elementów dobieraniu (filter) i zmodyfikować wartości, które pasują (map)

I jak sugeruje @TravisBrown, można również użyć flatMap, szczególnie w sytuacjach, gdy stan jest bardziej złożony i nie nadaje się jako warunek straży. Coś takiego na swoim przykładzie:

list.flatMap{ 
    case x if x % 2 == 0 => Some(x*2) 
    case x => None 
} 
+0

Nie zawsze jest możliwe lub wygodne sformułowanie twojego warunku w taki sposób, aby będzie działać jako strażnik, więc (IMO) dobra odpowiedź powinna zawierać 'flatMap' z' Option' (który jest również po prostu tak powszechnym idiomem w Scali, że warto go rozpoznać). –

+0

@TravisBrown, dobry punkt. Zawarłem to jako opcję w mojej odpowiedzi. Dzięki. – cmbaxter

+0

Jaki będzie rozmiar mojej ostatecznej listy, 5 czy 10? –

0

ten powinien wykonać pracę dla Ciebie:

Filtr pierwszy, gdy warunek jest p % 2 == 0 (do uzyskania tylko liczby parzyste).

a następnie użyć map pomnożyć te liczby parzyste przez 2.

var myList = List(1,2,3,4,5,6,7,8,9,10).filter(p => p % 2 == 0).map(p => {p*2}) 
+0

dlaczego spadki? –

+1

Mam tendencję do odrzucania wszystkich odpowiedzi tylko do kodu, które widzę, ale "Jak połączyć" część tytułu oznacza, że ​​nie jest to tak naprawdę odpowiedź. –

+0

Przegrałem ciebie. Nie szukałem. Dziękuję Ci. –

1

Jak @cmbaxter powiedział, zbierać określonym potrzebom doskonale. Drugą miłą rzeczą jest to, że zbierać dane z powstawaniem typ w przypadku jesteś filtrowany przez klasę:

scala> trait X 
// defined trait X 

scala> class Foo extends X 
// defined class Foo 

scala> class Bar extends X 
// defined class Bar 

scala> val xs = List(new Foo, new Bar, new Foo, new Bar) 
// xs: List[X] = List([email protected], [email protected], [email protected], [email protected]06f8) 

scala> xs.collect { case x: Foo => x } 
// res1: List[Foo] = List([email protected], [email protected]) 

na równi, filtr nie może być aż tak mądry (patrz List[Foo] vs List[X]):

scala> xs.filter { case x: Foo => true; case _ => false } 
// res3: List[X] = List([email protected], [email protected]) 
+0

Tylko szybkie przypuszczenie, ale myślę, że dzieje się tak dlatego, że '{case x: Foo => x}' jest wpisane jako 'PartialFunction [X, Foo]'. 'Foo' jest jedynym możliwym typem zwracania, więc' collect' już wie, że musi zbudować listę, która może zawierać 'Foo's. "filter", z drugiej strony, nie ma takiej wiedzy na temat pisania. – Adowrath

5

a dla zrozumienia (który rozkłada się do wewnątrz kombinacji map i withFilter), jak następuje,

for (x <- xs if x % 2 == 0) yield x*2 

Namel y

xs.withFilter(x => x % 2 == 0).map(x => x*2) 
0

Podobają mi się metody filtrowania.

val list1 = List(1,2,3,4,5,6,7,8,9,10) 
list1.filter(x => x%2 == 0).map(_*2) 
+0

Jak to się zasadniczo różni od odpowiedzi oferowanych przez elm lub cacho 2 lata temu? – jwvh

+0

@ jwvh dzięki za komentarz. To nieco inne podejście. Jest to kwestia preferencji, dlatego użyłem zwrotu "lubię". Wysłałem odpowiedź teraz, ponieważ miałem również to pytanie i sądziłem, że inni w przyszłości będą mieli możliwość spojrzenia na różne opcje. –

+0

Ale to nie jest inna opcja. Jest dokładnie taka sama, jak sugestia cacho. Jedyna różnica polega na użyciu podkreślenia w lambda 'map'. Dlaczego nie robisz tego samego w 'filter' lambda jest również ciekawy. – jwvh