Haskell五元Int元组重复检测函数优化需求问询
嘿,这个逐个两两比较的写法确实有点啰嗦,而且以后要是改成六元组、七元组,就得加一大堆新的条件判断,维护起来太麻烦了!给你几个更优雅的优化思路,既简洁又有扩展性:
首先先把你没写完的原代码补全(方便对比):
nothingIfMatch :: Maybe (Int, Int, Int, Int, Int) -> Maybe (Int, Int, Int, Int, Int) nothingIfMatch Nothing = Nothing nothingIfMatch (Just (a, b, c, d, e)) | a == b = Nothing | a == c = Nothing | a == d = Nothing | a == e = Nothing | b == c = Nothing | b == d = Nothing | b == e = Nothing | c == d = Nothing | c == e = Nothing | d == e = Nothing | otherwise = Just (a, b, c, d, e)
方案1:利用集合的唯一性(Data.Set)
集合的特性就是自动去重,我们可以把五元组转成列表,再转成集合,通过比较原列表长度和集合的大小来判断是否有重复元素:
import Data.Set (fromList, size) nothingIfMatch :: Maybe (Int, Int, Int, Int, Int) -> Maybe (Int, Int, Int, Int, Int) nothingIfMatch Nothing = Nothing nothingIfMatch val@(Just (a,b,c,d,e)) = let xs = [a,b,c,d,e] in if size (fromList xs) == length xs then val else Nothing
这个写法非常简洁,而且扩展性极强——哪怕以后要处理10元组,只要把列表里的元素对应补上就行,不用改逻辑。
方案2:排序后检查相邻元素
如果不想引入Data.Set的依赖,也可以用排序的思路:把元素排序后,重复的元素会挨在一起,只要检查有没有相邻元素相等就行:
import Data.List (sort) -- 辅助函数:把五元Int元组转成列表 tupleToList :: (Int, Int, Int, Int, Int) -> [Int] tupleToList (a,b,c,d,e) = [a,b,c,d,e] nothingIfMatch :: Maybe (Int, Int, Int, Int, Int) -> Maybe (Int, Int, Int, Int, Int) nothingIfMatch Nothing = Nothing nothingIfMatch val@(Just t) = let sorted = sort $ tupleToList t -- 把排序后的列表和它的尾部配对,检查有没有相邻相等的元素 hasDuplicate = any (\(x,y) -> x == y) $ zip sorted (tail sorted) in if hasDuplicate then Nothing else val
这个方法只用了基础的列表操作,不需要额外依赖,逻辑也很直观。
方案3:提取通用的全唯一检查函数
如果你的代码里经常需要检查元素是否全唯一,可以把这个逻辑抽成通用函数,让nothingIfMatch的逻辑更清晰:
import Data.Set (fromList, size) -- 通用函数:检查列表中所有元素是否唯一 allUnique :: Eq a => [a] -> Bool allUnique xs = size (fromList xs) == length xs -- 要是不想用Set,也可以用列表推导式实现: -- allUnique xs = and [x /= y | (x,i) <- zip xs [0..], (y,j) <- zip xs [0..], i < j] nothingIfMatch :: Maybe (Int, Int, Int, Int, Int) -> Maybe (Int, Int, Int, Int, Int) nothingIfMatch Nothing = Nothing nothingIfMatch val@(Just (a,b,c,d,e)) = if allUnique [a,b,c,d,e] then val else Nothing
这样一来,nothingIfMatch的核心逻辑就只剩“检查元素是否全唯一,是就返回原Just值,否则返回Nothing”,可读性拉满。
内容的提问来源于stack exchange,提问作者TheEnvironmentalist
相关产品推荐
相关产品推荐

