如何简化F#数组中不';不存在于另一个数组中?
我有两个F#数组要比较。对于其中一个函数,我必须找到数组1中的所有元素,这些元素在数组2中没有具有相同键字段的元素 我设法弄到了一些有用的东西,但我必须承认我现在读起来有点眼花了。我很同情开发人员,他们以后将不得不修改这个 在如何简化F#数组中不';不存在于另一个数组中?,f#,F#,我有两个F#数组要比较。对于其中一个函数,我必须找到数组1中的所有元素,这些元素在数组2中没有具有相同键字段的元素 我设法弄到了一些有用的东西,但我必须承认我现在读起来有点眼花了。我很同情开发人员,他们以后将不得不修改这个 在findWorkItemToClose函数中是否有一种更简单、更可读的方式来表达这一点 /// Gets the ICCM call number given a work item reference id. The reference id may have a das
findWorkItemToClose
函数中是否有一种更简单、更可读的方式来表达这一点
/// Gets the ICCM call number given a work item reference id. The reference id may have a dash number suffix on the call number.
let getIccmCallNumberFromReference (referenceId:string) =
if referenceId.Contains("-") then
referenceId.Substring(0, referenceId.IndexOf("-"))
else
referenceId
/// Gets the TFS work items where the ReferenceId no longer exists in the set of open Iccm calls.
let findWorkItemsToClose (allWorkItems:WorkItem[]) (iccmCalls:Iccm.IccmCall[]) =
let openStates = Set.ofList ["New"; "Approved"; "Commited"]
let openWorkItems = allWorkItems |> Array.filter (fun wi -> Set.contains wi.State openStates)
openWorkItems
|> Array.filter(fun wi ->
not (iccmCalls
|> Array.exists (fun ic ->
ic.CallNumber = getIccmCallNumberFromReference (wi.Fields.["ReferenceId"].Value.ToString()))))
更新:使用数组理解发布备选版本1(来自答案中的建议)和备选版本2
/// ALT 1: Gets the TFS work items where the ReferenceId no longer exists in the set of open Iccm calls.
let findWorkItemsToClose1 (allWorkItems : WorkItem []) (iccmCalls : Iccm.IccmCall []) =
let callNumbers = iccmCalls |> Array.map (fun ic -> ic.CallNumber) |> Set.ofArray
let openStates = Set.ofList ["New"; "Approved"; "Commited"]
let openWorkItems = allWorkItems |> Array.filter (fun wi -> Set.contains wi.State openStates)
openWorkItems
|> Seq.groupBy (fun wi -> getIccmCallNumberFromReference(wi.Fields.["ReferenceId"].Value.ToString()))
|> Seq.filter (fun (callNumber, _) -> not (Set.contains callNumber callNumbers))
|> Seq.collect snd
|> Seq.toArray
/// ALT 2: Gets the TFS work items where the ReferenceId no longer exists in the set of open Iccm calls.
let findWorkItemsToClose2 (allWorkItems : WorkItem []) (iccmCalls : Iccm.IccmCall []) =
let iccmCallNumbers = iccmCalls |> Array.map (fun ic -> ic.CallNumber) |> Set.ofArray
let openStates = Set.ofList ["New"; "Approved"; "Commited"]
let openWorkItems = allWorkItems |> Array.filter (fun wi -> Set.contains wi.State openStates)
[|
for workItem in openWorkItems do
let callNumberOnWorkItem = getIccmCallNumberFromReference(workItem.Fields.["ReferenceId"].Value.ToString())
if not (Set.contains callNumberOnWorkItem iccmCallNumbers) then
yield workItem
|]
不是100%确定这是你想要的,但如果我是对的,你可以:
seq
let getIccmCallNumberFromReference (referenceId : string) =
match referenceId.IndexOf "-" with
-1 -> referenceId
| 0 -> "" // to be consistent with the original function
| index -> referenceId.[.. index - 1]
let findWorkItemsToClose (allWorkItems : WorkItem []) (iccmCalls : Iccm.IccmCall []) =
// see comments if you choose to use a set instead of an array
let callNumbers = iccmCalls |> Array.distinctBy (fun ic -> ic.CallNumber) // |> Set.ofArray
allWorkItems
|> Seq.groupBy (fun wi -> getIccmCallNumberFromReference(wi.Fields.["ReferenceId"].Value.ToString()))
|> Seq.filter (fun (callNumber, _) -> not (Array.contains callNumber callNumbers)) // replace Array.contains by Set.contains
|> Seq.collect snd
|> Seq.toArray
这些都是很好的改进!iccmCalls.CallNumber是唯一的,所以我只是将其转换为Set。我非常喜欢Set.contains的使用,它使exists过滤器更容易掌握。getIccmCallNumberFromReference的新版本运行良好。对我来说,用[..index-1]索引字符串是新的。比子字符串更简洁。