【问题标题】:Is there a function in Haskell that would work like 'uniqueBy'?Haskell 中是否有像“uniqueBy”一样工作的函数?
【发布时间】:2020-11-21 15:46:14
【问题描述】:

我需要一个可以称为 uniqueBy 的函数,它会删除具有相同 snd 值,甚至没有像nubBy 那样保留其中一个。 例如,

uniqueBy [(1,1),(2,1)]

应该返回[],而

uniqueBy [(1,1),(1,1),(1,2)]

将返回[(1,2)]

遗憾的是,此功能 uniqueBy 不存在,我似乎无法找到替代功能或自己实现它的方法,尽管我确信必须有一个简单的方法.

【问题讨论】:

  • 这不会是一个库函数的简单应用。虽然它不是超级复杂,但您需要自己完成一些逻辑。
  • 应该uniqueBy [(1,1),(2,1)] 返回[(1,1)] 还是[]?以此类推是前者,但从你的描述来看是后者。是哪个?
  • @WillNess 它应该返回 []
  • 但下面的答案并没有这样做。它会返回第一个。也许你应该用澄清来编辑你的问题。
  • 一种方法是通过sort,然后groupBy,然后filtermap 运行您的列表,以仅保留其中包含多个元素的组并将结果转换为将每个分组到头元素的 snd 字段中。现在你有了 snd 值的列表来摆脱元组,所以在原始列表中添加另一个 filter,在谓词中使用 elem

标签: list haskell unique


【解决方案1】:

Data.List module 有一个nubBy :: (a -> a -> Bool) -> [a] -> [a] 函数。因此,您可以像这样使用它:

import Data.Function(on)
import Data.List(nubBy)

uniqueOnSnd :: Eq b => [(a, b)] -> [(a, b)]
uniqueOnSnd = nubBy ((==) `on` snd)

例如:

Main> uniqueOnSnd  [(4,1), (5,2), (3,1), (2,0)]
[(4,1),(5,2),(2,0)]

nubBy 需要,就像nubO(n2) 时间。因此,如果您可以对元素进行排序,则先排序并然后执行唯一性过滤器会更有效,例如:

import Data.Function(on)
import Data.List(sortBy)

nubOrderBy :: (a -> a -> Ordering) -> [a] -> [a]
nubOrderBy cmp = go . sortBy cmp
    where go (x1:xs) = x1 : go (dropWhile ((EQ ==) . cmp x1) xs)
          go [] = []

uniqueOnSnd :: Ord b => [(a, b)] -> [(a, b)]
uniqueOrdOnSnd = nubOrderBy (compare `on` snd)

这样做的一个缺点是它不能与无限列表一起工作,而且顺序不会被保留,但是这里 w 从而过滤掉 O(n log n 中的重复项).

【讨论】:

  • nubOrdOn from containers 的优点是可以保留元素的原始顺序。
  • @sjakobi:是的,这使用了Set。我想提供一个解决方案,而不使用其他包中的数据结构。当然,人们可以自己实现一个(树)集并确实提高成员检查。这也适用于无限列表,从那时起您只需使用 Set 并在枚举列表时更新它。
  • FYI OP 想要删除所有重复项,结果中一个也没有。
  • OP 已经在标题中提到了 nubBy 并说他们想要别的东西。
猜你喜欢
  • 1970-01-01
  • 2010-12-29
  • 1970-01-01
  • 1970-01-01
  • 2019-12-16
  • 2020-03-24
  • 1970-01-01
  • 1970-01-01
  • 2018-03-31
相关资源
最近更新 更多