gpt4 book ai didi

.net - F#:成对减少/聚合一个序列或列表

转载 作者:行者123 更新时间:2023-12-01 05:37:33 25 4
gpt4 key购买 nike

我对函数式编程还很陌生,并且在处理列表任务时遇到了一些问题。我有一组记录,如下所示:

type TestRec = {
Id : string
Amount : int }

现在我想删除列表中所有相互建立配对的项目。例如,如果有两个条目带有 Amount7-7 两者 项目应从列表中删除。如果有 Amount = 7 的第三个元素它应该留在列表中。

我希望你们能理解我在做什么。这是我到目前为止想出的(但它还不能正常工作):
let removeDoubles items =
items
|> Seq.groupBy (fun i -> Math.Abs(i.Amount))
|> Seq.map snd
|> Seq.filter (fun i -> Seq.length i = 1)

编辑:
确定两个元素是否相互匹配的函数可能比上述 ( Math.Abs ) 更复杂。我认为这将是 Amount 的一个很好的例子。值,但它可以是任何谓词函数。

编辑 2:
为了澄清一些,我想对可能的相关问题给出更现实的描述。您可以想象一个发票的计算,其中列表包含所有发票位置。现在,您要删除具有相同“商品编号”、“货币”和价格计算为零的所有发票头寸对。

也许这个例子有助于解释我的问题。我只是认为可能有一种更“实用的方法”来解决这个问题,而不是像我在命令式语言中那样在列表上运行两个循环并删除元素。

最佳答案

为了抽象出相反对的概念,我定义了两个函数。一种用于关系相等(相关),一种用于定义取消(相反)。

该函数的工作原理是首先将相关对象分组在一起,然后将它们划分为相对的数组。然后根据所需的取消次数对这些结果数组进行切片。最后一切都连接在一起。

type TestRec = {
Id : string;
Amount : int;
}

let removeDoubles items related opposite =
items
|> Seq.groupBy related
|> Seq.map (fun (key, values) ->
let t, f = values |> Seq.toArray |> Array.partition opposite
if t.Length > f.Length then
t.[.. t.Length - f.Length - 1]
else
f.[.. f.Length - t.Length - 1]
)
|> Seq.concat

let items = [
{Id="first";Amount=7};
{Id="seconds";Amount=7};
{Id="we";Amount=4};
{Id="negative";Amount= -7}
]

let test = removeDoubles
items
(fun x -> abs x.Amount)
(fun x -> x.Amount > 0)

printf "%A" test

System.Console.ReadLine() |> ignore

输出
seq [{Id = "first";
Amount = 7;}; {Id = "we";
Amount = 4;}]

关于.net - F#:成对减少/聚合一个序列或列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7822014/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com