Domanda

Devo essere in grado di scrivere una funzione che mostra parole ripetute da una stringa e restituire un elenco di stringhe in ordine di occorrenza e ignorare le non lettere

ad es. al prompt degli abbracci

repetitions :: String -> [String]

repetitions > "My bag is is action packed packed."
output> ["is","packed"]
repetitions > "My name  name name is Sean ."
output> ["name","name"]
repetitions > "Ade is into into technical drawing drawing ."
output> ["into","drawing"]
È stato utile?

Soluzione

Per dividere una stringa in parole, usa la funzione words (nel Preludio). Per eliminare caratteri non di parole, filter con Data.Char.isAlphaNum. Comprimi l'elenco con la coda per ottenere coppie adiacenti (x, y). Piega l'elenco, creando un nuovo elenco che contiene tutti x dove y == <=>.

Qualcosa del tipo:

repetitions s = map fst . filter (uncurry (==)) . zip l $ tail l
  where l = map (filter isAlphaNum) (words s)

Non sono sicuro che funzioni, ma dovrebbe darti un'idea approssimativa.

Altri suggerimenti

Sono nuovo in questa lingua, quindi la mia soluzione potrebbe essere una specie di brutta agli occhi di un veterano di Haskell, ma comunque:

let repetitions x = concat (map tail (filter (\x -> (length x) > 1) (List.group (words (filter (\c -> (c >= 'a' && c <= 'z') || (c>='A' && c <= 'Z') ||  c==' ') x)))))

Questa parte rimuoverà tutte le non lettere e non spazi da una stringa s :

filter (\c -> (c >= 'a' && c <= 'z') || (c>='A' && c <= 'Z') ||  c==' ') s

Questo dividerà una stringa s in parole e raggrupperà le stesse parole in elenchi che restituiscono un elenco di elenchi:

List.group (words s)

Quando questa parte rimuoverà tutti gli elenchi con meno di due elementi:

filter (\x -> (length x) > 1) s

Dopo quello che concateneremo tutti gli elenchi a uno rimuovendo un elemento da essi però

concat (map tail s)

Potrebbe non essere elegante, ma concettualmente è molto semplice. Suppongo che stia cercando parole duplicate consecutive come gli esempi.

-- a wrapper that allows you to give the input as a String
repititions :: String -> [String]
repititions s = repititionsLogic (words s)
-- dose the real work 
repititionsLogic :: [String] -> [String]
repititionsLogic [] = []
repititionsLogic [a] = []
repititionsLogic (a:as) 
    | ((==) a (head as)) = a : repititionsLogic as
    | otherwise = repititionsLogic as

Basandosi sulle risposte di Alexander Prokofyev:

repetitions x = concat (map tail (filter (\x -> (length x) > 1) (List.group (word (filter (\c -> (c >= 'a' && c <= 'z') || (c>='A' && c <= 'Z') || c==' ') x)))))

Rimuovi parentesi non necessarie:

repetitions x = concat (map tail (filter (\x -> length x > 1) (List.group (word (filter (\c -> c >= 'a' && c <= 'z' || c>='A' && c <= 'Z' || c==' ') x)))))

Usa $ per rimuovere più parentesi (ogni $ può sostituire una parentesi aperta se la parentesi finale è alla fine dell'espressione):

repetitions x = concat $ map tail $ filter (\x -> length x > 1) $ List.group $ word $ filter (\c -> c >= 'a' && c <= 'z' || c>='A' && c <= 'Z' || c==' ') x

Sostituisci gli intervalli di caratteri con le funzioni di Data.Char, unisci concat e mappa:

repetitions x = concatMap tail $ filter (\x -> length x > 1) $ List.group $ word $ filter (\c -> isAlpha c || isSeparator c) x

Utilizza una sezione e un curry in stile senza punti per semplificare (\x -> length x > 1) to ((>1) . length). Questo combina length con (& Gt; 1) (un operatore parzialmente applicato, o sezione ) in una pipeline da destra a sinistra.

repetitions x = concatMap tail $ filter ((>1) . length) $ List.group $ word $ filter (\c -> isAlpha c || isSeparator c) x

Elimina esplicito " x " variabile per rendere libera l'espressione complessiva senza punti:

repetitions = concatMap tail . filter ((>1) . length) . List.group . word . filter (\c -> isAlpha c || isSeparator c)

Ora l'intera funzione, che legge da destra a sinistra, è una pipeline che filtra solo caratteri alfa o separatori, la divide in parole, la suddivide in gruppi, filtra quei gruppi con più di 1 elemento, quindi riduce i gruppi rimanenti al primo elemento di ciascuno.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top