I'm currently doing a project for school about email identification but there is a certain part of the code that I have been stuck for quite a while, I've been trying to figure out how I could return Bool
if a certain value would repeat.
This is my current code:
The idea is to build a function that searches if a certain value is repeated
repeated :: [Char] -> Bool
repeated [] = False
repeated [_] = False
repeated (x:xs) = if elem x xs then True else repeated xs
At this part of the code I don't know how to specify the value that I want to return Bool if it repeats
special :: [String] -> [String]
special x = filter (elem ['.','_']) (map repeated x)
the expected output was this:
special "penuts.."
True
CodePudding user response:
Now that you have a solution, and so I don't feel I'm ruining a good learning experience, here are some additional implementation ideas that you might enjoy.
If you want to check a single character's repeated-ness status, you could ask for just the copies of that character, and then check whether there's two (or more) of them.
repeats :: Eq a => a -> [a] -> Bool
repeats a as = case filter (a==) as of
_:_:_ -> True
_ -> False
However, this might be less efficient if you have many repeats
queries you want to make. If that's so, you may want to preprocess the list, paying some up-front cost to make future queries faster. One way would be to count each of the elements.
import qualified Data.Map as M
count :: Ord a => [a] -> M.Map a Int
count as = M.fromListWith ( ) [(a, 1) | a <- as]
Given counts, it's easy to check whether a given character repeats.
repeats' :: Ord a => a -> M.Map a Int -> Bool
repeats' a as = M.findWithDefault 0 a as >= 2
For example, to check multiple characters for repetition at once, you might write:
multirepeats :: Ord a => [a] -> [a] -> Bool
multirepeats needle haystack = or [repeats' a as | a <- needle] where
as = count haystack
Giving the result of the call to count
a name in a where
block means it will be computed just once in each call to multirepeats
(at least, when using GHC).
If you wanted to check whether there is any repeating character, you could reuse count
like this:
anyRepeats :: Ord a => [a] -> Bool
anyRepeats = any (>=2) . count
Or, you could do this directly with list-based operations if you sort first:
import Data.List
anyRepeats' :: Ord a => [a] -> Bool
anyRepeats' as = not $ null [() | _:_:_ <- group (sort as)]
CodePudding user response:
After reviewing my function, i came across with the solution
element :: Eq t => t -> [t] -> Bool
element _[] = False
element x (y : ys) = if x == y then elem x ys else element x ys
if the specific value repeats, the boolean value output should be True:
element '.'"ban.nan."
True
CodePudding user response:
i also got my desire solution output:
repeatedLocal :: [Char] -> Bool
repeatedLocal [] = False
repeatedLocal [_] = False
repeatedLocal (x:xs) = if elem x ['.', '_'] then True else repeated xs