F# 使用不区分大小写的比较从集合中减去记录
我有一套记录:F# 使用不区分大小写的比较从集合中减去记录,f#,record,string-comparison,F#,Record,String Comparison,我有一套记录: 输入人物= { 名称:string 年龄:整数 } 让老人= 设置[{Name=“The Doctor”;年龄=1500}; {Name=“Yoda”;年龄=900}] 与上面的硬编码示例不同,数据集实际上来自一个数据源(对此我几乎没有控制权)。现在我需要从另一个数据源中减去一组数据。一般来说,第二个源中的数据是匹配的,但有时在资本化方面存在差异: 让困惑的人放弃他们的年龄= set[{Name=“THE DOCTOR”;Age=1500}] 当我尝试从第一个集合中减去第二个
输入人物=
{
名称:string
年龄:整数
}
让老人=
设置[{Name=“The Doctor”;年龄=1500};
{Name=“Yoda”;年龄=900}]
与上面的硬编码示例不同,数据集实际上来自一个数据源(对此我几乎没有控制权)。现在我需要从另一个数据源中减去一组数据。一般来说,第二个源中的数据是匹配的,但有时在资本化方面存在差异:
让困惑的人放弃他们的年龄=
set[{Name=“THE DOCTOR”;Age=1500}]
当我尝试从第一个集合中减去第二个集合时,它失败了,因为字符串比较区分大小写:
让那些知道自己年龄的人=
老年人-对他们的年龄感到困惑的人
val知道自己年龄的人:Set=
设置[{Name=“医生”;
年龄=1500;};{Name=“Yoda”;
年龄=900;}]
有没有一种方法可以对
人员
记录的姓名
字段执行不区分大小写的比较?这就是我迄今为止实现的方法,尽管可能有更好的方法
我的解决方案是重写People
记录上的Equals
函数,以便执行不区分大小写的比较。Set减法使用Equals
函数确定两条记录是否相互匹配。通过覆盖Equals
,我被迫(通过警告和错误)覆盖GetHashCode
,并实现IComparable
(以及设置CustomEquality
和CustomComparison
属性):
[]
类型人=
{
名称:string
年龄:整数
}
此为成员私有。\u内部ID=
this.Name.ToLower()+this.Age.ToString()
接口系统.i可与
请将此成员与obj进行比较=
让他人:人=沮丧的对象
此.\u internalId.CompareTo(其他.\u internalId)
覆盖此。等于(其他)=
相配
| :? 作为其他人的人->
System.String.Compare(this.\u internalId,other.\u internalId)=0
|_u->false
重写这个。GetHashCode()=
这是。_internalId.GetHashCode()
然而,这似乎起到了作用:
让老年人=
设置[{Name=“The Doctor”;年龄=1500};
{Name=“Yoda”;年龄=900}]
让困惑的人放弃他们的年龄=
set[{Name=“THE DOCTOR”;Age=1500}]
让那些知道自己年龄的人=
老年人-对他们的年龄感到困惑的人
val知道自己的年龄的人:Set=Set[{Name=“Yoda”;
年龄=900;}]
如果你知道一个更好的解决方案(涉及更少的代码),请发表它,而不是评论这个答案。我很乐意接受一个不那么冗长、笨拙的解决方案。这是我迄今为止实现的,尽管可能有更好的方法 我的解决方案是重写
People
记录上的Equals
函数,以便执行不区分大小写的比较。Set减法使用Equals
函数确定两条记录是否相互匹配。通过覆盖Equals
,我被迫(通过警告和错误)覆盖GetHashCode
,并实现IComparable
(以及设置CustomEquality
和CustomComparison
属性):
[]
类型人=
{
名称:string
年龄:整数
}
此为成员私有。\u内部ID=
this.Name.ToLower()+this.Age.ToString()
接口系统.i可与
请将此成员与obj进行比较=
让他人:人=沮丧的对象
此.\u internalId.CompareTo(其他.\u internalId)
覆盖此。等于(其他)=
相配
| :? 作为其他人的人->
System.String.Compare(this.\u internalId,other.\u internalId)=0
|_u->false
重写这个。GetHashCode()=
这是。_internalId.GetHashCode()
然而,这似乎起到了作用:
让老年人=
设置[{Name=“The Doctor”;年龄=1500};
{Name=“Yoda”;年龄=900}]
让困惑的人放弃他们的年龄=
set[{Name=“THE DOCTOR”;Age=1500}]
让那些知道自己年龄的人=
老年人-对他们的年龄感到困惑的人
val知道自己的年龄的人:Set=Set[{Name=“Yoda”;
年龄=900;}]
如果你知道一个更好的解决方案(涉及更少的代码),请发表它,而不是评论这个答案。我很乐意接受一个不那么冗长、笨拙的解决方案。这里是另一种方法:
type Name(value) =
member val Value = value
override this.Equals(that) =
match that with
| :? Name as name -> StringComparer.CurrentCultureIgnoreCase.Equals(this.Value, name.Value)
| _ -> false
override this.GetHashCode() =
StringComparer.CurrentCultureIgnoreCase.GetHashCode(this.Value)
type Person =
{
Name: Name
Age: int
}
{Name=Name("John"); Age=21} = {Name=Name("john"); Age=21} //true
以下是另一种方法:
type Name(value) =
member val Value = value
override this.Equals(that) =
match that with
| :? Name as name -> StringComparer.CurrentCultureIgnoreCase.Equals(this.Value, name.Value)
| _ -> false
override this.GetHashCode() =
StringComparer.CurrentCultureIgnoreCase.GetHashCode(this.Value)
type Person =
{
Name: Name
Age: int
}
{Name=Name("John"); Age=21} = {Name=Name("john"); Age=21} //true
只需添加
IComparable
实现,这就是OP想要的。我曾考虑过这种方法,但它确实使我使用Person记录的代码更加冗长。如果可能的话,我喜欢包含冗长的内容。如果您不想放弃F#records默认提供的结构相等/结构比较,那么您需要将字段或整个记录包装在一个类或联合中,在该类或联合中执行自定义相等/自定义比较。请参阅,例如,只需添加IComparable
实现,这正是OP想要的。我曾考虑过这种方法,但它确实会使我使用Person记录的代码更加冗长。如果可能的话,我喜欢包含冗长的内容。如果您不想放弃F#records默认提供的结构相等/结构比较,那么您需要将字段或整个记录包装在一个类或联合中,在该类或联合中执行自定义相等/自定义比较。见例。