Home > Net >  Haskell How to return a list of int from two int list
Haskell How to return a list of int from two int list

Time:06-24

if list1 = [14,24,1,2,11,7,23,8,12,22,20,0,15,19,4,9,10,21,18,17,3,13,16,5,6,25], and list2 = [14,14,24,24,1,1,2,2] How could I return a int list which is [0,0,1,1,2,2,3,3]

I have used the function

elemIndex' :: Eq a => a -> [a] -> Int
elemIndex' x = fromMaybe (-1) . elemIndex x

and the result for this for the first one 0 to get the index from list 1 for a single digit But what I want is

findIndex :: [Int] -> [Int] -> [Int] 

That would input two int list and return the index value base on the key list How could I recursively get the index for one list or using any import function, such as map.

CodePudding user response:

You've done a very good job of breaking the problem down. You've already recognized that you're doing the same thing for each element of the second list, and you've written a function to capture that behavior.

elemIndex' :: Eq a => a -> [a] -> Int
elemIndex' x = fromMaybe (-1) . elemIndex x

Now you want to take this function and apply it to each element of another list, collecting the results into a new list. That is, you want something that looks like

mystery :: (a -> b) -> [a] -> [b]

And we can search Hoogle and find exactly that function: map

map :: (a -> b) -> [a] -> [b]

map takes a function and a list and applies it to each element. You've got a function (elemIndex', with appropriate partial application), and you've got a list (list2 in your example). So let's put it together.

findAll :: Eq a => [a] -> [a] -> [Int]
findAll haystack needles = map (\x -> elemIndex' x haystack) needles

There are lots of streaming functions in Haskell like map, and knowing / figuring out which one to use in a given situation comes with practice. If you're ever in doubt, remember that you can use Hoogle to search for a type or you can simply do whatever you're trying to do recursively (if you didn't know map existed, you could write it yourself with a bit of recursion), and you'll get the hang of it over time. Good luck in your Haskell endeavors!

CodePudding user response:

As an alternative to the answer by @SilvioMayolo, you could use a Map data structure. We zip in the indexes for each value in list1 and then turn that into a map, then just do a lookup for each value in list2.

import Data.Map
import Data.List

list1 = [14,24,1,2,11,7,23,8,12,22,20,0,15,19,4,9,10,21,18,17,3,13,16,5,6,25]
list2 = [14,14,24,24,1,1,2,2]

map1 = Data.Map.fromList $ list1 `zip` [0..]
-- fromList [(0,11),(1,2),(2,3),(3,20),(4,14),(5,23),(6,24),
--           (7,5),(8,7),(9,15),(10,16),(11,4),(12,8),(13,21),
--           (14,0),(15,12),(16,22),(17,19),(18,18),(19,13),
--           (20,10),(21,17),(22,9),(23,6),(24,1),(25,25)]

list3 = Data.List.map (map1 !) list2
-- [0,0,1,1,2,2,3,3]
  • Related