Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List haskell列表中的唯一元素_List_Haskell - Fatal编程技术网

List haskell列表中的唯一元素

List haskell列表中的唯一元素,list,haskell,List,Haskell,好的,这可能会出现在序曲中,但是:有没有标准的库函数来查找列表中唯一的元素?为了澄清,我的(重新)实施是: 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

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

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
我在上搜索
(Eq a)=>[a]->[a]

第一个结果是(从列表中删除重复的元素)


Hoogle非常棒。

来自
数据的
nub
函数。List
(不,它实际上不在前奏曲中)确实做了一些您想要的事情,但它与您的
独特的
函数并不完全相同。它们都保留元素的原始顺序,但
unique
保留最后一个顺序 每个元素的引用,而
nub
保留第一个引用

您可以这样做,使
nub
的行为完全像
一样独特
,如果这很重要的话(尽管我感觉不是这样):

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

如果将类型限制为具有Ord实例的类型,则可以使其更好地扩展。
nub
上的这种变化仍然保留列表元素的顺序,但其复杂性是
O(n*logn)


事实上,它一直在向
数据添加
nubOrd
;也就是说,原始列表中出现多次的任何元素都不应包含在结果中

我可以提出另一个定义吗,独特的替代:

    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 :: [Int] -> [Int]
unique xs = [x | (x,y) <- zip xs [0..], x `notElem` (take y xs)]
unique::[Int]->[Int]

唯一xs=[x |(x,y)在Haskell中创建唯一列表的算法:

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"}
输出:

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"}

我想这就行了

unique [] = []
unique (x:xs) = x:unique (filter ((/=) x) xs)

你的
has
也是标准的;它只是
flip elem
。或者甚至
has xs=(`elem`xs)
@yatima2975为什么你要使用
elem
作为中缀?@dopatraman因为
elem
具有类型
Eq a=>a->[a]->Bool
,所以将它用作中缀操作部分使
xs
成为第二个参数。
(`elem`xs)
被设计成
(\x->elem x xs)
,这正是我们在这里想要的!此外,您可以像这样提供自己的相等函数:nubBy::(a->a->Bool)->[a]->[a]如果巴特有时间的话,我们可能会看到一个nubOrd,这在性能方面会更合理。值得一提的是,
nub
函数来自
Data.List
包。@Thomas:Data.List.Unique有一个sortUniq,这是您请求的“nubOrd”。我宁愿使用一个(Eq a,Hashable a)=>[a]->[a]这将更加合理,从性能角度来看……到目前为止,我真的很难理解如何有效地使用Hoogle,从未想过搜索我正在寻找的类型签名。有争议的是,最好将其作为一个集合,而不是首先使用列表。老实说:
nub
对任何lis都不好t、 即使在包含两个元素的列表中,nubOrd也是。这有点像一个“映射筛”,类似于不纯的“散列筛”。函数类型签名中有一个输入错误。应该是
Ord a
。此外,我发现nubOrd令人惊讶(或者不是)在我的例子中,它并不比nub好。它甚至更慢。可能是因为没有太多的重复值(虽然引入nub将运行时间减少了一半,但nub ord比nub慢了大约20%)@alternative,列表上的函数通常比集合上的等效函数更有用,因为它们可以维护项的顺序。这一点非常重要。事实上,这就是Data.List.Unique(Unique)的定义。虽然我个人从未使用过该用例,但“挤压列表以仅包含一个重复项”函数是许多操作的基础,它改变了元素的顺序。
Foo {id_ = 9, name_ = "Name"}
Foo {id_ = 9, name_ = "Gaby"}
Foo {id_ = 5, name_ = "Karl"}
Foo {id_ = 8, name_ = "Tim"}
unique [] = []
unique (x:xs) = x:unique (filter ((/=) x) xs)