代码之家  ›  专栏  ›  技术社区  ›  muhmuhten

haskell列表中的唯一元素

  •  50
  • muhmuhten  · 技术社区  · 15 年前

    好吧,这可能会出现在序曲中,但是:是否有一个标准的库函数用于查找列表中的唯一元素?为了澄清,我的(重新)实施是:

    has :: (Eq a) => [a] -> a -> Bool
    has [] _ = False
    has (x:xs) a
      | x == a    = True
      | otherwise = has xs a
    
    unique :: (Eq a) => [a] -> [a]
    unique [] = []
    unique (x:xs)
      | has xs x  = unique xs
      | otherwise = x : unique xs
    
    7 回复  |  直到 14 年前
        1
  •  57
  •   user3637541    8 年前

    nub 函数来自 Data.List (不,它实际上不在序曲中)确实做了一些你想要的,但是它和你的不完全一样 unique 保留最后一个 保留第一个引用。

    表现得一模一样 独特的 ,如果这很重要(尽管我觉得不是):

    unique = reverse . nub . reverse
    

    也, 只适用于小列表。 它的复杂性是二次的,所以如果你的列表可以包含数百个元素,那么它就开始变慢。

    如果将类型限制为具有Ord实例的类型,则可以使其更好地扩展。 O(n * log n) :

    import qualified Data.Set as Set
    
    nubOrd :: Ord a => [a] -> [a] 
    nubOrd xs = go Set.empty xs where
      go s (x:xs)
       | x `Set.member` s = go s xs
       | otherwise        = x : go (Set.insert x s) xs
      go _ _              = []
    

    事实上,它已经 proposed 添加 nubOrd Data.Set

        2
  •  99
  •   Artelius    15 年前

    我在找 (Eq a) => [a] -> [a] Hoogle .

    nub (从列表中删除重复的元素)。

    胡格尔太棒了。

        3
  •  12
  •   Daniel Patru    12 年前
    import Data.Set (toList, fromList)
    uniquify lst = toList $ fromList lst
    
        4
  •  4
  •   Adam Grant    13 年前

    我可以建议另一种定义,独特的替代:

        unique_alt :: [Int] -> [Int]
        unique_alt [] = []
        unique_alt (x:xs)
            | elem x ( unique_alt xs ) = [ y | y <- ( unique_alt xs ), y /= x ]
            | otherwise                = x : ( unique_alt xs )
    

    以下是一些突出显示unique alt和unqiue之间差异的示例:

        unique     [1,2,1]          = [2,1]
        unique_alt [1,2,1]          = [2]
    
        unique     [1,2,1,2]        = [1,2]
        unique_alt [1,2,1,2]        = []
    
        unique     [4,2,1,3,2,3]    = [4,1,2,3]
        unique_alt [4,2,1,3,2,3]    = [4,1]
    
        5
  •  2
  •   Craig Norton    6 年前

    我想这样就行了。

    unique [] = []
    unique (x:xs) = x:unique (filter ((/=) x) xs)
    
        6
  •  1
  •   Manuel    9 年前

    data Foo = Foo { id_ :: Int
                   , name_ :: String
                   } deriving (Show)
    
    alldata = [ Foo 1 "Name"
              , Foo 2 "Name"
              , Foo 3 "Karl"
              , Foo 4 "Karl"
              , Foo 5 "Karl"
              , Foo 7 "Tim"
              , Foo 8 "Tim"
              , Foo 9 "Gaby"
              , Foo 9 "Name"
              ]
    
    isolate :: [Foo] -> [Foo]
    isolate [] = []
    isolate (x:xs) = (fst f) : isolate (snd f)
      where
        f = foldl helper (x,[]) xs
        helper (a,b) y = if name_ x == name_ y
                         then if id_ x >= id_ y
                              then (x,b)
                              else (y,b)
                         else (a,y:b)
    
    main :: IO ()
    main = mapM_ (putStrLn . show) (isolate alldata)
    

    输出:

    Foo {id_ = 9, name_ = "Name"}
    Foo {id_ = 9, name_ = "Gaby"}
    Foo {id_ = 5, name_ = "Karl"}
    Foo {id_ = 8, name_ = "Tim"}
    
        7
  •  0
  •   Juan Kujarchi    12 年前

    unique :: [Int] -> [Int]
    unique xs = [x | (x,y) <- zip xs [0..], x `notElem` (take y xs)]
    
    推荐文章