F#:如何识别哈希表中具有多个值的键?
F#: How to identify keys that have multiple values in a HashTable?
我目前正在开发一个初学者项目来实现我自己的重复文件查找器。这是我第一次使用.NET 语言,所以我对.NET API 仍然非常陌生。
这是我到目前为止编写的代码:
open System
open System.IO
open System.Collections.Generic
let directory = @somePath
let getAllFiles (directory : string) =
Directory.GetFiles(directory)
let getFileInfo (directory : string) =
directory
|> getAllFiles
|> Seq.map (fun eachFile -> (eachFile, new FileInfo(eachFile)))
let getFileLengths (directory: string) =
directory
|> getFileInfo
|> Seq.map (fun (eachFile, eachFileInfo : FileInfo) -> (eachFile, eachFileInfo.Length))
// If two files have the same lengths, they might be duplicates of each other.
let groupByFileLengths (directory: string) =
directory
|> getFileLengths
|> Seq.groupBy snd
|> Seq.map (fun (fileLength, files) -> fileLength, files |> Seq.map fst |> List.ofSeq)
let findGroupsOfTwoOrMore (directory: string) =
directory
|> groupByFileLengths
|> Seq.filter (snd >> List.length >> (<>) 1)
let constructHashtable (someTuple) =
let hashtable = new Hashtable()
someTuple
|> Seq.iter hashtable.Add
hashtable
let readAllBytes (tupleOfFileLengthsAndFiles) =
tupleOfFileLengthsAndFiles
|> snd
|> Seq.map (fun eachFile -> (File.ReadAllBytes eachFile, eachFile))
|> constructHashtable
我想做的是以每个文件的字节数组为键,文件名本身为值构造一个散列table。如果多个不同文件名的文件共享同一个 bye 数组,那么它们就是重复的,我的目标是删除重复的文件。
我查看了 MSDN 上的 Hashtable 命名空间,但没有识别包含多个值的 hashtable 键的方法。
编辑:这是我尝试实现 MD5:
let readAllBytesMD5 (tupleOfFileLengthsAndFiles) =
let md5 = MD5.Create()
tupleOfFileLengthsAndFiles
|> snd
|> Seq.map (fun eachFile -> (File.ReadAllBytes eachFile, eachFile))
|> Seq.map (fun (byteArray, eachFile) -> (md5.ComputeHash(byteArray), eachFile))
|> Seq.map (fun (hashCode, eachFile) -> (hashCode.ToString, eachFile))
请指教我如何改进和继续,因为我因为没有牢牢掌握 MD5 的工作原理而被困在这里。谢谢。
Hashtable
不支持同一键的多个值 - 当您尝试使用同一键添加第二个条目时会出现异常。它也是无类型的,您应该几乎总是喜欢类型化的可变 System.Collections.Generic.Dictionary
或不可变的 F# Map
.
您要找的是 Map<byte array, Set<string>>
。这是我的看法:
let buildMap (paths: string array) =
paths
|> Seq.map (fun eachFile -> (File.ReadAllBytes eachFile, eachFile))
|> Seq.groupBy fst
|> Seq.map (fun (key, items) ->
key, items |> Seq.map snd |> Set.ofSeq)
|> Map.ofSeq
顺便说一句,除非您比较的是非常非常小的文件,否则使用整个文件内容作为关键字不会让您走得太远。您可能希望研究为这些文件生成校验和并改为使用它们。
我目前正在开发一个初学者项目来实现我自己的重复文件查找器。这是我第一次使用.NET 语言,所以我对.NET API 仍然非常陌生。
这是我到目前为止编写的代码:
open System
open System.IO
open System.Collections.Generic
let directory = @somePath
let getAllFiles (directory : string) =
Directory.GetFiles(directory)
let getFileInfo (directory : string) =
directory
|> getAllFiles
|> Seq.map (fun eachFile -> (eachFile, new FileInfo(eachFile)))
let getFileLengths (directory: string) =
directory
|> getFileInfo
|> Seq.map (fun (eachFile, eachFileInfo : FileInfo) -> (eachFile, eachFileInfo.Length))
// If two files have the same lengths, they might be duplicates of each other.
let groupByFileLengths (directory: string) =
directory
|> getFileLengths
|> Seq.groupBy snd
|> Seq.map (fun (fileLength, files) -> fileLength, files |> Seq.map fst |> List.ofSeq)
let findGroupsOfTwoOrMore (directory: string) =
directory
|> groupByFileLengths
|> Seq.filter (snd >> List.length >> (<>) 1)
let constructHashtable (someTuple) =
let hashtable = new Hashtable()
someTuple
|> Seq.iter hashtable.Add
hashtable
let readAllBytes (tupleOfFileLengthsAndFiles) =
tupleOfFileLengthsAndFiles
|> snd
|> Seq.map (fun eachFile -> (File.ReadAllBytes eachFile, eachFile))
|> constructHashtable
我想做的是以每个文件的字节数组为键,文件名本身为值构造一个散列table。如果多个不同文件名的文件共享同一个 bye 数组,那么它们就是重复的,我的目标是删除重复的文件。
我查看了 MSDN 上的 Hashtable 命名空间,但没有识别包含多个值的 hashtable 键的方法。
编辑:这是我尝试实现 MD5:
let readAllBytesMD5 (tupleOfFileLengthsAndFiles) =
let md5 = MD5.Create()
tupleOfFileLengthsAndFiles
|> snd
|> Seq.map (fun eachFile -> (File.ReadAllBytes eachFile, eachFile))
|> Seq.map (fun (byteArray, eachFile) -> (md5.ComputeHash(byteArray), eachFile))
|> Seq.map (fun (hashCode, eachFile) -> (hashCode.ToString, eachFile))
请指教我如何改进和继续,因为我因为没有牢牢掌握 MD5 的工作原理而被困在这里。谢谢。
Hashtable
不支持同一键的多个值 - 当您尝试使用同一键添加第二个条目时会出现异常。它也是无类型的,您应该几乎总是喜欢类型化的可变 System.Collections.Generic.Dictionary
或不可变的 F# Map
.
您要找的是 Map<byte array, Set<string>>
。这是我的看法:
let buildMap (paths: string array) =
paths
|> Seq.map (fun eachFile -> (File.ReadAllBytes eachFile, eachFile))
|> Seq.groupBy fst
|> Seq.map (fun (key, items) ->
key, items |> Seq.map snd |> Set.ofSeq)
|> Map.ofSeq
顺便说一句,除非您比较的是非常非常小的文件,否则使用整个文件内容作为关键字不会让您走得太远。您可能希望研究为这些文件生成校验和并改为使用它们。