sorting - 在 Excel-Dna 中对 Excel“变体”进行排序的 F# 函数
问题描述
当尝试使用以下函数对一维变体数组进行排序时(这里的“变体”是指所有 Excel 类型,例如布尔、双精度(和日期)、字符串、各种错误......):
[<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 有一个自然的排序功能,我想效仿(至少大致如此)。例如双(和日期)<字符串<布尔<错误...
我的问题:在 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
推荐阅读
- apache-spark-sql - 在 sas 中合并 - 在 python 中合并
- terraform - 如果 user_data 未能运行完成,如何创建 aws_instance 失败
- spring-boot - 在 log4j2 配置中使用 TimeBasedTriggeringPolicy
- css - Vue Js 过渡只在进入时有效,不离开时有效
- web-scraping - 如何使用 Web Scraper 或其他替代方法抓取大量(>800)Google 我的地图位置数据(“来自 Google 地图的详细信息”)?
- node.js - Parse Server - 从后端使用 Apple 登录
- android - npm install for react-navigation-drawer 不工作
- eclipse - 如何将 eclipse formatter.xml 转换为 Checkstyle 规则
- python - 如何使用“包含”过滤器进行查询但不区分大小写?
- java - 安卓。JSON 解析器在我的新模块中返回 null