在列表中查找重复元素的基本功能是什么?
翻译后,如何简化以下功能:
let numbers = [ 3;5;5;8;9;9;9 ]
let getDuplicates = numbers |> List.groupBy id
|> List.map snd
|> List.filter (fun set -> set.Length > 1)
|> List.map (fun set -> set.[0])
我肯定这是个复制品。但是,我无法在这个网站上找到这个问题。
更新
let getDuplicates numbers =
numbers |> List.groupBy id
|> List.choose (fun (k,v) -> match v.Length with
| x when x > 1 -> Some k
| _ -> None)
发布于 2016-04-06 20:59:16
简化了函数
每当您有一个过滤器和一个映射之后,您可能可以用一个选择替换这两个过滤器。选择的目的是为列表中的每个值运行一个函数,并且只返回返回某些值的项(不移除任何值,这是筛选器部分)。无论您在其中放置了什么值,都是地图部分:
let getDuplicates = numbers |> List.groupBy id
|> List.map snd
|> List.choose( fun( set ) ->
if set.Length > 1
then Some( set.[0] )
else None )
我们可以通过移除地图再走一步。在这种情况下,保持包含键的元组是有帮助的,因为它不需要获取列表的第一项:
let getDuplicates = numbers |> List.groupBy id
|> List.choose( fun( key, set ) ->
if set.Length > 1
then Some key
else None )
这比原来的更简单吗?也许吧。因为选择结合了两个目的,因此它必然比分开的目的( filter和map)更加复杂,这使得人们很难一目了然地理解它,也许会取消更“简化”的代码。稍后再谈这个。
分解概念
不过,简化代码并不是直接的问题。您询问了在查找重复项时有用的函数。在高层次上,你如何找到一个副本?这取决于您的算法和特定需求:
我的观点是,一份完整的函数列表有助于查找副本,它读起来就像现有集合函数的“谁是谁”--这完全取决于您要做的事情和您的具体需求。我认为您对List.groupBy和List.choose的选择可能非常简单。
可维护性的简化
关于简化的最后一个想法是记住,简化代码会在一定程度上提高代码的可读性。超出这一点的“简化”很可能涉及到诡计,或模糊的意图。如果我回顾几周前编写的代码示例和几个项目,那么最短、也许最简单的代码可能不是最容易理解的。因此,最后一点--简化未来的代码可维护性--可能是您的目标。如果是这样的话,您的原始算法只修改了groupBy元组,并对管道的每一步所做的工作添加了注释,这可能是您的最佳选择:
// combine numbers into common buckets specified by the number itself
let getDuplicates = numbers |> List.groupBy id
// only look at buckets with more than one item
|> List.filter( fun (_,set) -> set.Length > 1)
// change each bucket to only its key
|> List.map( fun (key,_) -> key )
最初的问题评论已经表明,对于不熟悉代码的人来说,您的代码是不清楚的。这是一个经验问题吗?一定。但是,无论我们是在一个团队中工作,还是孤军奋战,优化代码(在可能的情况下)快速理解应该是每个人的首要任务。(从沙箱上爬下来) :)
不管怎样祝你好运。
发布于 2016-04-06 16:23:42
如果您不介意在本地范围内使用可变集合,则可以这样做:
open System.Collections.Generic
let getDuplicates numbers =
let known = HashSet()
numbers |> List.filter (known.Add >> not) |> set
发布于 2016-04-06 16:00:40
您可以将最后三个操作包装在一个List.choose
中
let duplicates =
numbers
|> List.groupBy id
|> List.choose ( function
| _, x::_::_ -> Some x
| _ -> None )
https://stackoverflow.com/questions/36455768
复制相似问题