compare string contents in haskell - list

I have a 2 lists of strings
eg:
listx = ["name","age","rank"]
input = ["name","age"]
How can I compare the two lists to check whether the listx contains "name" & "age" given in input?

B is a subset of A iff B \ A is empty
so another way to do it is
import Data.List ((\\))
null (input \\ listx)

all (flip elem listx) input
comes to mind. No idea how efficient it is though...

Is this homework? :)
You need to create one or two recursive functions to walk through both lists, and search for every string in the input.
Or, you could look up some good functions in the Prelude that helps here.

One more way.
import Data.Set
(fromList input) `isSubsetOf` (fromList listX)

Related

how to combine map and replicate on an array of integers

For a school exercise i need to generate a series of symbols with a given array of numbers. given is [3,3,2,1] output "+===+===+==+=+".
My approach would be to use map and replicate "=" on the array then intercalate "+" and finally concat the array to a single string.
My solution is something like this (while standing knee deep in errors)
printLine arr = map (replicate "=") arr >>> intercalate '*' >>> concat
what is the correct syntax? or shouldn't i use map at all?
you are on the right track, you just mixed up the functions a bit:
replicate will take a number n and repeat the second argument n-times into a list (so you just got the order wrong - you could use flip or an aux. function like I did bellow)
you have to watch out if you want Char or String ('=' VS "=" for example) - read the type-definitions (try :t intercalate or Hoogle) carefully and remember: String ~ [Char]!
intercalate actually does the concatenation so you don't need concat at all
Here is a almost working version:
eqSigns :: Int -> String
eqSigns n = replicate n '='
mixIn :: [Int] -> String
mixIn = intercalate "+" . map eqSigns
try it and see if you get the missing parts in there ;)
here is the version with flip instead:
mixIn :: [Int] -> String
mixIn = intercalate "+" . map (flip replicate '=')
PS: are you coming from some ML/F# background?

Using regex to access values from a map in keys

val m = Map("a"->2,"ab"->3,"c"->4)
scala> m.get("a");
scala> println(res.get)
2
scala> m.get(/a\.*/)
// or something similar.
Can i get a list of all key-value pairs where key contains "a" without having to iterate over the entire map , by doing something as simple as specifying a regex in the key value?
Thanks in advance!
No, you cannot do that without iterating over the entire map. In fact, I can't even think of a single data structure that would allow it, say nothing of the API.
Of course, iterating is pretty simple:
m.filterKeys(_ matches "a.*")

Get decimals from String

I got a function that takes a string and search it for decimals and output them.
What I got so far is:
getDecimal :: String -> [Int]
getDecimal[] = 0
getDecimal (x:y:xs) =
if
isDecimal x y
then
//output list
else
getDecimal xs
(for example: getDecimal "he12llo035" will output 12 , 035
But cant fill in the then because I simply cant find the solution, can you guys give me tips?
You try to tackle this in an imperative-like way: "look at this part of the list, is it what we want? Well then do that thing... oh, no it's not? Well then proceed there..."
It sure can't hurt to know how to implement it in such terms as well, but anyway better to learn more concise, explanative, declarative approaches right away. "The Haskell way".
That normally means roughly: split up your goal in subtasks. You'll first want to group all numbers down to one element, rather than a group of characters within the list. Well, you can hoogle for "group"!
Indeed there's a group comparison, but it simply puts together elements that are equal. That's a bit too strong, we sure want to allow different digits in each number! groupBy is the version that allows this. So, according to what do we want to group? Well, depending on whether it's a number. There's a nice helper from the Data.Function module that allows you to formulate this very much to the point:
groupBy ((==) `on` isDigit)
Meaning, we want to group such elements that have "the same status of digit-being".
After that, you'll have a lists of strings, and know each string is either a complete number, or something unrelated. The latter is to be thrown away...
filter (isDigit . head)
(I've just checked if the first character is a digit; the following are sure to be as well because that's what we've grouped by.
Now you've a list of numbers still in string form, all that's left to be done is parse (read!) each of them.
import Data.Char
import Data.List
import Data.Function
getDecimalNums :: String -> [Int]
getDecimalNums = map read . filter (isDigit . head) . groupBy ((==) `on` isDigit)

SML pair tuples conversion

I've been trying to solve this pair tuples problem where the input is a list of tuples and the output is a tuple of lists where the first element of each tuple is grouped together and similarly with the second (i.e. [(1,2),(3,4),(5,6)] --> ([1,3,5],[2,4,6])).
I've thought of this code but it gives me an error:
fun convert L = foldl (fn ((x,y),(u,v)) => ((u#x),(v#y)) ([],[]) L;
Any suggestions for a fix?
Concatenation (#) takes two lists, but x and y are values, so you need to wrap them with [] to make a single-element list:
fun convert l=foldl (fn((x,y),(u,v))=>(u#[x],v#[y])) (nil,nil) l
You can use cons instead of concatenation, though the lists inside the returned tuple are reversed:
fun convert l=foldl (fn((x,y),(u,v))=>(x::u,y::v)) (nil,nil) l
# concatenates lists (and x and y are not lists).
Try (u#[x],v#[y]).
Note, however, that appending is a linear-time operation, while prepending (i.e. x::u) is constant. As Alex pointed out, this will build your lists in reverse, but you can resolve this by processing your input in reverse as well - i.e., by using foldr instead of foldl.

Filtering list of tuples

New to Haskell and have a stumbling block. I'm trying to filter a list of tuples based on the first item.
filter (==(x,_)) lis
I get an illegal '_' error, but I'm not sure how I can get around it?
In Haskell, you cannot iterate over a tuple like you can a list.
If the tuple only has two items, you can use fst to retrieve the first item of the tuple and snd to retrieve the second item.
One way to do what I think you want to do is this approach:
Prelude> let lst = [(1,2), (3,4)]
Prelude> filter ((==1).fst) lst
[(1,2)]
Which only returns the items in the list where the first element is equal to 1; of course, you can substitute x where I put 1.
To be a little more specific, (==1).fst first applies fst to the element in lst, then applies (==1) to the result of fst -- technically, the dot composes the two functions together.
You can't give an argument with a wildcard _ in it to the == operator (or to any other function). The argument needs to be a real value, not a pattern that should be matched against.
If you want to use pattern matching you could use a lambda function as you filter condition:
filter (\(a,_) -> a == x) lis
Also, there is the predefined function fst to extract the first element of a two-element tuple. This can be combined with == to do the same test:
filter ((== x) . fst)) lis