Chcę przekonwertować [1,2,3,4]
na [[1 2] [2 3] [3 4]]
lub [(1 2) (2 3) (3 4)]
. W clojure mam (partition 2 1 [1,2,3,4])
. Jak mogę to zrobić w haskell? Podejrzewam, że jest taka funkcja w standardowym API, ale nie mogę jej znaleźć.Pary elementów z listy
Odpowiedz
Standardowa Sztuką jest to, aby zip
lista z własnym tail
:
> let xs = [1,2,3,4] in zip xs (tail xs)
[(1,2),(2,3),(3,4)]
Aby zrozumieć, dlaczego to działa, w kolejce na liście i ogonem wizualnie.
xs = 1 : 2 : 3 : 4 : []
tail xs = 2 : 3 : 4 : []
i zauważ, że zip
czyni krotki z każdej kolumny.
Istnieją dwa powody, dla których bardziej subtelne to zawsze robi to, co trzeba:
zip
przystanki gdy albo lista zabraknie elementów. Ma to sens, ponieważ nie możemy mieć "niepełnej pary" na końcu i zapewnia to, że nie otrzymamy żadnych par z listy pojedynczych elementów.- Gdy
xs
jest pusty, można oczekiwać, żetail xs
wyrzuci wyjątek. Jednakże, ponieważzip
najpierw sprawdza swój pierwszy argument, gdy widzi, że jest to pusta lista, drugi argument nigdy nie jest oceniany.
Wszystko powyżej odnosi się również do zipWith
, więc możesz użyć tej samej metody, gdy chcesz zastosować funkcję parowania do sąsiednich elementów.
Dla standardowego rozwiązania, takiego jak Clojure's partition
, nie ma nic w standardowych bibliotekach. Można jednak spróbować czegoś takiego:
partition' :: Int -> Int -> [a] -> [[a]]
partition' size offset
| size <= 0 = error "partition': size must be positive"
| offset <= 0 = error "partition': offset must be positive"
| otherwise = loop
where
loop :: [a] -> [[a]]
loop xs = case splitAt size xs of
-- If the second part is empty, we're at the end. But we might
-- have gotten less than we asked for, hence the check.
(ys, []) -> if length ys == size then [ys] else []
(ys, _) -> ys : loop (drop offset xs)
, więc nie ma w nim żadnej standardowej funkcji w standardowej bibliotece, np. Jeśli nie chcesz mieć krotek, ale trzykrotnie lub jeśli chcę powtórzyć lub pominąć pewne wartości, tak jak http://clojuredocs.org/clojure_core/clojure.core/partition – piotrek
@piotrek: Nic w standardowych bibliotekach, nie, jednak nie jest to trudne do wdrożenia. Dodałem przykładową implementację do mojej odpowiedzi – hammar
Wystarczy rzucić kolejną odpowiedź się tam przy użyciu innego podejścia:
Dla n = 2 chcesz po prostu zip
listy z ogonem. Dla n = 3 chcesz spakować listę ogonem i ogonem. Ten wzór kontynuuje dalej, więc wszystko, co musimy zrobić, to uogólnić go:
partition n = sequence . take n . iterate tail
Ale to działa tylko na przesunięcie 1. Aby uogólnić przesunięcia musimy tylko spojrzeć na genrated listy. Zawsze będzie miał postać:
[[1..something],[2..something+1],..]
Więc wszystko pozostało do zrobienia, to wybrać każdą offset
th element i powinniśmy być w porządku. shamelessy Wygrałem tę wersję z @ertes z this question:
everyNth :: Int -> [a] -> [a]
everyNth n = map head . takeWhile (not . null) . iterate (drop n)
Cała funkcja staje się teraz:
partition size offset = everyNth offset . sequence . take size . iterate tail
Niestety twoja generalizacja daje jakąś dziwną permutację – flq
- 1. Konwersja elementów na klucz, pary wartości
- 2. Usuwanie elementów pustych z listy
- 3. usuwania duplikatów pary z listy <object>
- 4. zbierać każdą parę elementów z listy do krotek w Pythonie
- 5. Łączenie elementów listy
- 6. Sztuczki dla elementów pływających wewnątrz elementów listy
- 7. Usuwanie elementów z jednej listy w innej
- 8. Usuwanie ostatnich elementów N z listy
- 9. Prolog usuwa wiele elementów z listy
- 10. Najdłuższy łańcuch elementów z listy w Pythonie
- 11. Dodawanie elementów do listy z linq var
- 12. Python - porównywanie elementów listy z elementami "sąsiednimi"
- 13. R: usuwanie elementów NULL z listy
- 14. Zagnieżdżanie elementów listy w elementach listy uporządkowanej listy?
- 15. pythonowy sposób drukowania elementów listy
- 16. Jak grupować według listy elementów?
- 17. pyton wszystkich możliwych par 2 Wykaz elementów, a uzyskanie indeksu tej pary
- 18. Dodawanie elementów do listy Java
- 19. Usuń wiele elementów listy (Python)
- 20. wyłączanie i wyszarzanie elementów listy
- 21. Permutowane kombinacje elementów listy - Prolog
- 22. Wyrównanie w poziomie elementów listy
- 23. Kolejność elementów listy spełniających warunek
- 24. Podział elementów listy w pythonie
- 25. zapobiec wyświetlaniu listy wybranych elementów
- 26. Scala: Lista pary do pary list
- 27. Bardziej ogólnie funkcja liczby pasujących elementów wśród elementów n listy
- 28. wybieranie elementów z listy zgodnie z ich etykietami z drugiej listy
- 29. Jak dodać dwie listy elementów do jednej listy?
- 30. Zliczanie łącznej liczby elementów listy w widoku listy
Dlaczego wezwanie Clojure to 'partition'? Jeśli coś podzielisz, podzielisz w taki sposób, że jest to suma części. – AndrewC
Och - znaleziono [clojure docs] (http://clojuredocs.org/clojure_core/clojure.core/partition) opisujące "partition n step coll: zwraca leniwą sekwencję list o n elementach każda, w krokach przesunięcia oddzielnie.Jeśli krok nie zostanie podany, domyślnie n, partycje nie zachodzą na siebie. " – AndrewC