2012-05-01 11 views
8

Sono nuovo di Haskell e sto solo cercando di scrivere una lista di comprensione per calcolare la frequenza di ciascun valore distinto in una lista, ma ho problemi con l'ultima parte ..Haskell - Conteggio quante volte ogni elemento distinto in una lista si verifica

Finora ho questo:

frequency :: Eq a => [a] -> [(Int,a)] 
frequency list = [(count y list,y) | y <- rmdups ] 

C'è qualcosa di sbagliato con l'ultima parte che coinvolge rmdups.

La funzione di conteggio prende un personaggio e poi un elenco di caratteri e spiega come si verifica spesso che il carattere, il codice è il seguente ..

count :: Eq a => a -> [a] -> Int 
count x [] = 0 
count x (y:ys) | x==y = 1+(count x ys) 
       | otherwise = count x ys 

di ringraziamento in anticipo.

+7

Quindi, "c'è qualcosa che non va con la parte ultima che coinvolge rmdups", ma non ci dicono che cosa è sbagliato, quale (eventuale) messaggio di errore o output si ottiene, e non si mostra la definizione (o anche solo il tipo) di 'rmdups'. Come dovremmo rispondere? – delnan

+0

Scusa Ho scritto rmdups lì quando in realtà intendevo nub – user1353742

risposta

0

La tua funzione rmdups è solo nub da Data.List.

10

ho dovuto usare Ord nel posto di Eq a causa dell'uso di sort

frequency :: Ord a => [a] -> [(Int,a)] 
frequency list = map (\l -> (length l, head l)) (group (sort list)) 
+4

usando 'Control.Arrow',' frequency = map (length &&& head). gruppo. sort' – cdk

+0

@cdk Sembra interessante. Non potresti espanderci in una risposta, potresti? –

4

Supponendo rmdups ha il tipo

rmdups :: Eq a => [a] -> [a] 

Poi ti manca un parametro per esso.

frequency :: Eq a => [a] -> [(Int,a)] 
frequency list = [(count y list,y) | y <- rmdups list] 

Ma l'errore che si ottiene sarebbe utile per la diagnosi.

0

Sostituire rmdups con nub list ha funzionato per me come un fascino.

10

Si potrebbe anche usare un/carta finita array associativo per memorizzare le associazioni di elementi della lista a loro conteggio mentre sei al computer le frequenze: l'utilizzo

import Data.Map (fromListWith, toList) 

frequency :: (Ord a) => [a] -> [(a, Int)] 
frequency xs = toList (fromListWith (+) [(x, 1) | x <- xs]) 

Esempio:

> frequency "hello world" 
[(' ',1),('d',1),('e',1),('h',1),('l',3),('o',2),('r',1),('w',1)] 

vedere la documentazione di fromListWith e toList.

6

Come richiesto, ecco una soluzione che utilizza Control.Arrow:

frequency :: Ord a => [a] -> [(Int,a)] 
frequency = map (length &&& head) . group . sort 

Questa è la stessa funzione di risposta ThePestest s', ad eccezione

λl -> (length l, head l) 

viene sostituito con

-- simplified type signature 
(&&&) :: (a -> b) -> (a -> c) -> a -> (b, c) 

da Control.Arrow.Se si vuole evitare l'importazione,

liftA2 (,) :: Applicative f => f a -> f b -> f (a, b) 

funziona così (utilizzando l'istanza applicativo di (->) r)

+0

Nel caso qualcuno stia cercando una soluzione standard, esiste un metodo 'count' in [' Data.List.Unique'] (https://hackage.haskell.org/package/Unique-0.4.7.2 /docs/Data-List-Unique.html). L'implementazione è abbastanza simile a quella fornita in questa risposta. –

Problemi correlati