2013-04-12 10 views
7

Witam, potrzebuję uzyskać n-ty element listy, ale bez użycia !! operator. Jestem niezmiernie nowy w haskell, więc byłbym wdzięczny, gdybyś mógł odpowiedzieć bardziej szczegółowo, a nie tylko jednym wierszem kodu. To, co próbuję w tej chwili:Haskell - pobierz n-ty element bez "!!"

nthel:: Int -> [Int] -> Int 
nthel n xs = 0 
let xsxs = take n xs 
nthel n xs = last xsxs 

Ale dostaję: Błąd składni (ewentualnie nieprawidłowe wcięcia)

Z góry dziękuję!

+1

'let xsxs = take n xs' - co to ma zrobić? – Adrian

Odpowiedz

12

Dużo to trochę off tutaj,

nthel :: Int -> [Int] -> Int 

jest technicznie poprawne, naprawdę chcemy

nthel :: Int -> [a] -> a 

Więc możemy to wykorzystać na listach czegokolwiek (opcjonalnie)

nthel n xs = 0 

To, co właśnie powiedziałeś, brzmi "Bez względu na to, co dajesz nthel return 0". co jest oczywiście błędne.

let xsxs = ... 

To nie jest legalne haskell. let ... in ... jest wyrażeniem, nie można go użyć.

Stamtąd nie jestem pewien, co to ma zrobić.

Może to pomoże umieścić na właściwym torze

nthelem n [] = <???> -- error case, empty list 
nthelem 0 xs = head xs 
nthelem n xs = <???> -- recursive case 

Spróbuj wypełnienie <???> z najlepszych odgadnięcia i jestem szczęśliwy, aby pomóc stamtąd.

Alternatywnie można użyć składni "dopasowywania wzorców" Haskella. Wyjaśniam, jak możesz to zrobić z listami here.

który zmienia nasz wyżej

nthelem n [] = <???> -- error case, empty list 
nthelem 0 (x:xs) = x --bind x to the first element, xs to the rest of the list 
nthelem n (x:xs) = <???> -- recursive case 

Rozwiązanie to jest przydatne, ponieważ eliminuje konieczność używania jawnych head i tail s.

+0

"Stamtąd nie jestem pewien, co to ma zrobić." Próbuję wyciąć listę do n-tego elementu, a następnie wziąć ostatni (tj. N-ty element). Zorientowałem się, że to najprostszy sposób na uzyskanie n-tego elementu bez !!. Jeśli wiesz coś prostszego, możesz je udostępnić. W każdym razie, dziękuję za odpowiedź! – user43051

+0

Zrobiłem, to jest całe dno tego wpisu. – jozefg

+0

To jest to, z czym się szamotam - jak wstawić i zająć w . Przepraszam za głupie pytania, ale robię haskell przez kilka godzin. – user43051

8

myślę, że oznaczało to:

nthel n xs = last xsxs 
    where xsxs = take n xs 

... co można uprościć jako:

nthel n xs = last (take n xs) 
+0

Dokładnie! Dziękuję Ci! Wy dwaj, zagłosujcie na siebie, ponieważ moja ocena jest zbyt niska, by zrobić to samemu. :) – user43051

+3

@ user43051 Żałuję, że nie mogłem się upomnieć! :) Nie ma za co. –

+0

działa tylko wtedy, gdy ta lista jest co najmniej tak długi jak żądany wskaźnik jak się powraca do N lub długość liście, nthel 15 „abc” Powrót „c”, a nie nic. –

1

myślę, że należy unikać w miarę możliwości last - listy są do stosowania z "przód", a nie od tyłu. To, czego chcesz, to pozbyć się pierwszych n elementów, a następnie uzyskać głowę z pozostałej listy (oczywiście pojawi się błąd, jeśli reszta jest pusta).Można wyrazić to dość bezpośrednio jako:

nthel n xs = head (drop n xs) 

Albo krócej:

nthel n = head . drop n 

lub lekko szalony:

nthel = (head .) . drop 
0

Jak wiemy listy nie są naturalnie indeksowane, ale może być pokonać za pomocą wspólnych wskazówek.

Spróbuj na ghci, zip [0..] "hello", Co to jest zip [0,1,2] "hello" lub zip [0..10] "hello"?
Począwszy od tej obserwacji, możemy teraz łatwo uzyskać sposób indeksowania naszej listy.
Ponadto jest dobrą ilustracją wykorzystania lenistwa, dobrą wskazówką do procesu uczenia się.

Następnie na podstawie tego i przy użyciu dopasowywania wzorców możemy zapewnić skuteczny algorytm.

  1. Zarządzanie ograniczeniami (pusta lista, indeks ujemny).
  2. Zastąp listę przez zindeksowaną wersję przy użyciu suwaka.
  3. Zadzwoń do projektu funkcji pomocnika, aby przetworzyć rekurencyjnie naszą indeksowaną listę.

teraz do funkcji pomocniczych, wykaz nie może być pusta wtedy możemy wzór mecz naiwnie, a

  • jeśli nasz indeks jest równa n mamy zwycięzcę
  • innego, jeśli nasz następny element jest pusty, to ponad
  • w przeciwnym razie wywołaj funkcję pomocnika z następnym elementem.

Uwaga dodatkowa, ponieważ nasza funkcja może się nie udać (pusta lista ...) dobrze byłoby zawinąć nasz wynik za pomocą Może typ.

Łączymy to wszystko razem.

nth :: Int -> [a] -> Maybe a 
nth n xs 
    | null xs || n < 0 = Nothing 
    | otherwise  = helper n zs 
     where 
     zs = zip [0..] xs 
     helper n ((i,c):zs) 
      | i == n = Just c 
      | null zs = Nothing 
      | otherwise = helper n zs