Jak podzielić listę elementów na listy zawierające maksymalnie N elementów?
przykład: mając listę z 7 elementami, utwórz grupy po 4, pozostawiając ostatnią grupę możliwie z mniejszą liczbą elementów.
split(List(1,2,3,4,5,6,"seven"),4)
=> List(List(1,2,3,4), List(5,6,"seven"))
O wiele łatwiej jest wykonać to zadanie metodą ślizgową. Działa to w ten sposób:
Powiedzmy, że chcesz podzielić listę na mniejsze listy o rozmiarze 3.
da tobie
źródło
Lub jeśli chcesz stworzyć własny:
Posługiwać się:
edytuj : po przejrzeniu tego 2 lata później nie polecałbym tej implementacji, ponieważ
size
jest O (n), a zatem ta metoda to O (n ^ 2), co wyjaśniałoby, dlaczego wbudowana metoda staje się szybsza dla dużych list, jak zauważono w komentarzach poniżej. Możesz skutecznie wdrożyć w następujący sposób:lub nawet (nieco) wydajniej używając
splitAt
:źródło
xs splitAt n
jest alternatywą dla kombinacjixs take n
ixs drop n
splitAt
zamiasttake
/drop
poprawia wydajność średnio o około 4%; oba są o 700-1000% szybsze niż.grouped(n).toList
!grouped-toList
jest tak wolny? To brzmi jak błąd.grouped
nie istniał :)), prostota jest nadrzędnym czynnikiem. W standardowej bibliotece stabilność i wydajność powinny być ważniejsze od elegancji. Ale jest wiele przykładów zarówno w Programowaniu w Scali, jak iw standardowych bibliotekach wywołań normalnie rekurencyjnych (zamiast rekurencyjnych ogonowych); to standardowa i ważna broń w skrzynce z narzędziami FP.Dodam rekurencyjną wersję metody split, ponieważ była dyskusja na temat rekurencji ogonowej w porównaniu z rekurencją. Użyłem adnotacji tailrec, aby zmusić kompilator do narzekania w przypadku, gdy implementacja nie jest rzeczywiście rekuzyjna tailrec. Uważam, że rekurencja ogona zamienia się w pętlę pod maską, a zatem nie spowoduje problemów nawet w przypadku dużej listy, ponieważ stos nie będzie rosnąć w nieskończoność.
źródło
Myślę, że jest to implementacja wykorzystująca splitAt zamiast take / drop
źródło