F# 按给定标准对记录序列/集合进行分组或聚合
我对函数式编程还很陌生,因此 F# 和我很难为这个问题找到正确的解决方案。
我有一系列记录类型,例如:
type Invoice = {
GrpText : string
GrpRef : int
Article : int
Wkz : int
Text : string
Price : decimal
InvoiceRef : int
}
现在我想按给定标准对发票序列进行分组或聚合,即对它们的价格求和。不符合条件的发票
不应分组,而应按原样返回。
标准函数可能如下所示:
/// determines whether to group the two given Invoice items or not
let criteria item toCompareWith =
(item.GrpRef > 0 && item.Article = toCompareWith.Article
&& item.InvoiceRef = toCompareWith.InvoiceRef) ||
(item.Wkz <> 0 && item.Text = toCompareWith.Text)
聚合或分组可能如下所示:
/// aggregate the given Invoice items
let combineInvoices item1 item2 =
{item1 with Price = item1.Price + item2.Price; Wkz = 0}
问题看起来有点简单,但我目前在函数式编程方面没有足够的经验来连接点。
编辑:
我刚刚修改了criteria
函数,以便更好地表明它可能比按一个或多个字段分组更复杂一些。
I am pretty new to functional programming and therefore F# and I have serious trouble to come up with the right solution for this problem.
I have got a sequence of record types, say like:
type Invoice = {
GrpText : string
GrpRef : int
Article : int
Wkz : int
Text : string
Price : decimal
InvoiceRef : int
}
Now I want to group or aggregate the sequence of Invoices
by a given criteria and i.e. sum their prices. Invoices
that does not match the criteria should not be grouped and just returned as they are.
A criteria function might look like this:
/// determines whether to group the two given Invoice items or not
let criteria item toCompareWith =
(item.GrpRef > 0 && item.Article = toCompareWith.Article
&& item.InvoiceRef = toCompareWith.InvoiceRef) ||
(item.Wkz <> 0 && item.Text = toCompareWith.Text)
The aggregation or grouping could look like this:
/// aggregate the given Invoice items
let combineInvoices item1 item2 =
{item1 with Price = item1.Price + item2.Price; Wkz = 0}
The problem looks kind of simple but I am currently not experienced enough in functional programming to connect the dots.
Edit:
I just modified the criteria
function in order to better show that it might be a bit more complex than grouping by one or multiple fields.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
除非我遗漏了什么,否则涉及两个步骤:分组和减少。最简单的分组方法是
Seq.groupBy
。由于您想使用自定义相等性,因此需要将[]
属性应用于您的类型并覆盖Equals
和GetHashCode
,或者推出您自己的使用您的平等概念的密钥生成函数。这是后者的一个例子。用法
Unless I'm missing something, there are two steps involved: group and reduce. The easiest way to group is
Seq.groupBy
. Since you want to use custom equality you need to either apply the[<CustomEquality>]
attribute to your type and overrideEquals
andGetHashCode
, or roll your own key generating function that uses your concept of equality. Here's an example of the latter.Usage
像这样的 Defaultinvoice 是某种“0”发票
编辑 - 对于更复杂的组合功能。
因此,如果您的组合函数更复杂,最好的方法可能是使用递归,我认为很难避免 O(n^2) 解决方案。我会选择类似的解决方案,
该解决方案既没有功能,也可能非常慢,但它应该适用于任意复杂的组合函数
Something like this where Defaultinvoice is some sort of '0' invoice
EDIT - For more complicated combine function.
So if your combine function is more complicated, the best approach is probably to use recursion and I think it is going to be hard to avoid a O(n^2) solution. I would go with something like
This solution is both highly non-functional and probably very slow, but it should work for arbitrarily complicated combination functions