Home > Back-end >  Return Bool if a specific value repeats
Return Bool if a specific value repeats

Time:02-02

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
  • Related