如何在元组列表中找到所有最小元素?
How to find all minimum elements in a list of tuples?
如何找到列表中的所有最小元素?现在我有一个元组列表,即
[(10,'a'),(5,'b'),(1,'c'),(8,'d'),(1,'e')]
所以我想要在新列表中输出列表的所有最小元素。例如
[(1,'c'),(1,'e')]
我试过了
minimumBy (comparing fst) xs
但那只是returns第一个最小元素。
获得第一个值的最小值后,我们可以根据这些项目过滤列表。因为你在这里想要检索最少项目的列表,我们可以通过返回一个空列表来覆盖空列表:
minimumsFst :: Ord a => [(a, b)] -> [(a, b)]
minimumsFst [] = []
minimumsFst xs = filter ((==) minfst . fst) xs
where minfst = minimum (map fst xs)
例如:
Prelude> minimumsFst [(10,'a'),(5,'b'),(1,'c'),(8,'d'),(1,'e')]
[(1,'c'),(1,'e')]
您也可以使用 foldr
轻松完成:
minimumsFst :: Ord a => [(a, b)] -> [(a, b)]
minimumsFst xs = go (minfst xs) xs
where
go mn ls = foldr (\(x, y) rs -> if (x == mn) then (x,y) : rs else rs) [] xs
minfst ls = minimum (map fst ls)
以你的例子:
minimumsFst [(10,'a'),(5,'b'),(1,'c'),(8,'d'),(1,'e')]
=> [(1,'c'),(1,'e')]
单线。关键是排序。
Prelude Data.List> let a = [(1,'c'),(2,'b'),(1,'w')]
Prelude Data.List> (\xs@((m,_):_) -> takeWhile ((== m) . fst ) xs) . sortOn fst $ a
[(1,'c'),(1,'w')]
你试过了
minimumBy (comparing fst) xs
也可以写成
= head . sortBy (comparing fst) $ xs
= head . sortOn fst $ xs
= head . head . group . sortOn fst $ xs
= head . head . groupBy ((==) `on` fst) . sortOn fst $ xs
这 returns 只是第一个元素而不是它们的列表,所以只需删除额外的 head
即可获得您想要的内容:
= head . groupBy ((==) `on` fst) . sortOn fst $ xs
当然 head
不好,因为它会在 []
输入时出错。相反,我们可以使用安全选项,
= concat . take 1 . groupBy ((==) `on` fst) . sortOn fst $ xs
顺便说一下,任何调用 minimum
的解决方案对于空输入列表也是不安全的:
> head []
*** Exception: Prelude.head: empty list
> minimum []
*** Exception: Prelude.minimum: empty list
但是takeWhile
是安全的:
> takeWhile undefined []
[]
edit: 由于懒惰,即使在最坏的情况下,最终版本的整体时间复杂度仍应为 O(n)案例.
这是一个一次性解决方案(这里的大多数其他答案都执行两遍:一次找到最小值,一次过滤它),并且不依赖于排序函数的实现方式高效。
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Foldable (foldl')
minimumsBy :: forall a. (a -> a -> Ordering) -> [a] -> [a]
minimumsBy _ [] = []
minimumsBy f (x:xs) = postprocess $ foldl' go (x, id) xs
where
go :: (a, [a] -> [a]) -> a -> (a, [a] -> [a])
go acc@(x, xs) y = case f x y of
LT -> acc
EQ -> (x, xs . (y:))
GT -> (y, id)
postprocess :: (a, [a] -> [a]) -> [a]
postprocess (x, xs) = x:xs []
请注意,我在这里使用的 [a] -> [a]
类型称为 difference list, aka a Hughes list。
如何找到列表中的所有最小元素?现在我有一个元组列表,即
[(10,'a'),(5,'b'),(1,'c'),(8,'d'),(1,'e')]
所以我想要在新列表中输出列表的所有最小元素。例如
[(1,'c'),(1,'e')]
我试过了
minimumBy (comparing fst) xs
但那只是returns第一个最小元素。
获得第一个值的最小值后,我们可以根据这些项目过滤列表。因为你在这里想要检索最少项目的列表,我们可以通过返回一个空列表来覆盖空列表:
minimumsFst :: Ord a => [(a, b)] -> [(a, b)]
minimumsFst [] = []
minimumsFst xs = filter ((==) minfst . fst) xs
where minfst = minimum (map fst xs)
例如:
Prelude> minimumsFst [(10,'a'),(5,'b'),(1,'c'),(8,'d'),(1,'e')]
[(1,'c'),(1,'e')]
您也可以使用 foldr
轻松完成:
minimumsFst :: Ord a => [(a, b)] -> [(a, b)]
minimumsFst xs = go (minfst xs) xs
where
go mn ls = foldr (\(x, y) rs -> if (x == mn) then (x,y) : rs else rs) [] xs
minfst ls = minimum (map fst ls)
以你的例子:
minimumsFst [(10,'a'),(5,'b'),(1,'c'),(8,'d'),(1,'e')]
=> [(1,'c'),(1,'e')]
单线。关键是排序。
Prelude Data.List> let a = [(1,'c'),(2,'b'),(1,'w')]
Prelude Data.List> (\xs@((m,_):_) -> takeWhile ((== m) . fst ) xs) . sortOn fst $ a
[(1,'c'),(1,'w')]
你试过了
minimumBy (comparing fst) xs
也可以写成
= head . sortBy (comparing fst) $ xs
= head . sortOn fst $ xs
= head . head . group . sortOn fst $ xs
= head . head . groupBy ((==) `on` fst) . sortOn fst $ xs
这 returns 只是第一个元素而不是它们的列表,所以只需删除额外的 head
即可获得您想要的内容:
= head . groupBy ((==) `on` fst) . sortOn fst $ xs
当然 head
不好,因为它会在 []
输入时出错。相反,我们可以使用安全选项,
= concat . take 1 . groupBy ((==) `on` fst) . sortOn fst $ xs
顺便说一下,任何调用 minimum
的解决方案对于空输入列表也是不安全的:
> head [] *** Exception: Prelude.head: empty list > minimum [] *** Exception: Prelude.minimum: empty list
但是takeWhile
是安全的:
> takeWhile undefined [] []
edit: 由于懒惰,即使在最坏的情况下,最终版本的整体时间复杂度仍应为 O(n)案例.
这是一个一次性解决方案(这里的大多数其他答案都执行两遍:一次找到最小值,一次过滤它),并且不依赖于排序函数的实现方式高效。
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Foldable (foldl')
minimumsBy :: forall a. (a -> a -> Ordering) -> [a] -> [a]
minimumsBy _ [] = []
minimumsBy f (x:xs) = postprocess $ foldl' go (x, id) xs
where
go :: (a, [a] -> [a]) -> a -> (a, [a] -> [a])
go acc@(x, xs) y = case f x y of
LT -> acc
EQ -> (x, xs . (y:))
GT -> (y, id)
postprocess :: (a, [a] -> [a]) -> [a]
postprocess (x, xs) = x:xs []
请注意,我在这里使用的 [a] -> [a]
类型称为 difference list, aka a Hughes list。