简体   繁体   中英

How to find index in a zipped list by condition of the elements of tuples (Haskell)

I am new an familiarizing myself to Haskell and yet don't know how to work around problems like this:

I have a zipped (from a Bool and an Int list) list of tuples that have (Bool, Int) form. How can I find index of the (one) element that has values True as first and 'minimum of the seconds' as second? Is there any fancy library functions I can use?

Since the first element is a Bool you can filter on it by using just fst :

filter fst l

In the more general case you'll have a type a and a predicate p :: a -> Bool . Then you would filter by composing p with fst :

filter (p . fst) l

Now for the second step, you want to find the minimum based on a custom criteria (as opposed to the default compare ). That's exactly what minimumBy from Data.List does. It expects a comparison function of type (a -> a -> Ordering) . You can write your own comparison function but there is a better way using on from Data.Function. To find the minimum element looking at the second elements you would say:

minimumBy (compare `on` snd)

Finding the index is left as an exercise.

I'm guessing your real goal here is to find the value of the minimum, and you can do that without knowing the position of the minimum.

If you need to handle the case of an empty list, then you just return a Maybe type, since the minimum of an empty list is undefined.

Here are two possibilities: getMin, and getMin2

import Data.List (sortBy, foldl')

head' :: [a] -> Maybe a
head' [] = Nothing
head' (a:as) = Just a

getMin  :: [(Bool, Int)] -> Maybe (Bool, Int)
getMin  vs = head' $ sortBy (\i j -> compare (snd i) (snd j)) $ filter fst vs

getMin2 :: [(Bool, Int)] -> Maybe Int
getMin2 vs = foldl' r Nothing vs where
    r (Just i) (b,j) = case (b, compare j i) of
                          (True, LT) -> Just j
                          otherwise  -> Just i
    r Nothing (b,j)  = case b of
                          True  -> Just j
                          False -> Nothing

Data.List> getMin  [(True, 4), (False, 0), (True, 3)]
Just (True,3)
Data.List> getMin2  [(True, 4), (False, 0), (True, 3)]
Just 3

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM