尝试对一维变体数组进行排序时(这里用“变体”表示所有Excel类型,例如bool,double(和日期),string,各种错误...),其功能如下:
[<ExcelFunction(Category="test", Description="sort variants.")>]
let sort_variant ([<ExcelArgument(Description= "Array to sort.")>] arr : obj[]): obj[] =
arr
|> Array.sort
我收到以下错误:Error FS0001 The type 'obj' does not support the 'comparison' constraint. For example, it does not support the 'System.IComparable' interface
,这可能意味着在所有obj类型上都没有通用的排序功能。
但是Excel具有自然的排序功能,我想模仿该功能(至少可以理解)。例如,双精度(和日期)<字符串<bool <错误...
我的问题:在F#/ Excel-Dna中对“变量”数组进行排序的惯用方式是什么?(我在一个接受obj[]
并返回的函数之后obj[]
,没有别的,不是宏...)
我的(临时?)解决方案:我创建了一个“歧视的工会”类型
type XLVariant = D of double | S of string | B of bool | NIL of string
(不确定NIL是否必要,但并没有造成伤害。同样,在我的现实生活代码中,我添加了一个DT of DateTime
实例,因为我需要区分双精度型的日期)。
let toXLVariant (x : obj) : XLVariant =
match x with
| :? double as d -> D d
| :? string as s -> S s
| :? bool as b -> B b
| _ -> NIL "unknown match"
let ofXLVariant (x : XLVariant) : obj =
match x with
| D d -> box d
| S s -> box s
| B b -> box b
| NIL _ -> box ExcelError.ExcelErrorRef
[<ExcelFunction(Category="test", Description="sort variants.")>]
let sort_variant ([<ExcelArgument(Description= "Array to sort.")>] arr : obj[]): obj[] =
arr
|> Array.map toXLVariant
|> Array.sort
|> Array.map ofXLVariant
(为简单起见,我错过了Errors类型,但是想法是一样的)
这对我来说似乎更加明确,因为它仅遵循CLR类型系统:
// Compare objects in the way Excel would
let xlCompare (v1 : obj) (v2 : obj) =
match (v1, v2) with
| (:? double as d1), (:? double as d2) -> d1.CompareTo(d2)
| (:? double), _ -> -1
| _, (:? double) -> 1
| (:? string as s1), (:? string as s2) -> s1.CompareTo(s2)
| (:? string), _ -> -1
| _, (:? string) -> 1
| (:? bool as b1), (:? bool as b2) -> b1.CompareTo(b2)
| (:? bool), _ -> -1
| _, (:? bool) -> 1
| _ -> 2
[<ExcelFunction(Category="test", Description="sort variants.")>]
let sort_variant ([<ExcelArgument(Description= "Array to sort.")>] arr : obj[]): obj[] =
Array.sortWith xlCompare arr
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句