Dictionary 在不知道密钥的情况下,如何从F#Map中获取第一个密钥、值对?

Dictionary 在不知道密钥的情况下,如何从F#Map中获取第一个密钥、值对?,dictionary,f#,key-value,Dictionary,F#,Key Value,在不知道密钥的情况下,如何从F#获取第一个密钥、值对 我知道映射类型用于在给定键的情况下获取相应的值,例如 我也知道人们可以把地图转换成列表,然后使用列表 List.head (Map.toList map) 我想这样做 1.没有钥匙 2.不知道键和值的类型 3.不使用可变的 4.无需迭代整个地图 5.无需进行转换,该转换将遍历SEED后面的整个地图,例如map.toList等 我还知道,如果获得第一个键、值对,它可能没有用处,因为map文档没有说明在两个不同调用中使用map是否保证相同的顺序

在不知道密钥的情况下,如何从F#获取第一个
密钥、值对

我知道映射类型用于在给定键的情况下获取相应的值,例如

我也知道人们可以把地图转换成列表,然后使用列表

List.head (Map.toList map)
我想这样做
1.没有钥匙
2.不知道键和值的类型
3.不使用可变的
4.无需迭代整个地图
5.无需进行转换,该转换将遍历SEED后面的整个地图,例如map.toList等

我还知道,如果获得第一个
键、值对
,它可能没有用处,因为map文档没有说明在两个不同调用中使用map是否保证相同的顺序

如果无法编写代码,则可以接受来自MSDN等网站的现有参考,解释并说明原因

TLDR

我是如何解决这个问题的,是如何转换这个函数的:

let findmin l = 
    List.foldBack
        (fun (_,pr1 as p1) (_,pr2 as p2) -> if pr1 <= pr2 then p1 else p2)
        (List.tail l) (List.head l)
该列表用于解析具有优先级的二进制运算符表达式,其中字符串为二进制运算符,int为优先级。其他函数是在数据上执行的,因此使用F#map可能比list更有优势。我还没有决定最终的解决方案,但我想在map仍然处于最前沿的时候探索这个问题

目前我正在使用:

let findmin m =
    if Map.isEmpty m then 
        None
    else
        let result = 
            Map.foldBack 
                (fun key value (k,v) -> 
                    if value <= v then (key,value) 
                    else (k,v))
                m ("",1000)
        Some(result)
是的,这是对地图进行分区,但不起作用,例如

let infixes = ["+",10; "-",10; "*",20; "/",20]
let infixMap = infixes |> Map.ofList
let mutable test = true
let fx k v : bool =
    if test then 
        printfn "first"
        test <- false
        true
    else 
        printfn "rest"
        false
let (first,rest) = Map.partition fx infixMap
关于答案的注释 对于优先解析的实际目的,最好在最终转换中看到
-
之前的
+
操作,因此需要在
-
之前返回
+
。因此,答案的这种变化

let-findmin(map:map)=map |>Seq.minBy(fun-kvp->kvp.Value)
实现这一点,并通过

让findmin m=
Map.foldBack(趣味k2 v2 st->
匹配
|当v1st时,一些(k1,v1)
|部分(k2,v2))无
使用
Seq.head
确实会返回
map
中的第一个项目,但是必须注意,
map
是用排序的键构造的,因此对于我的实际示例,我想从最低值
10
开始,因为项目是按
key
排序的,所以返回的第一个是
(“*”,20)
,其中
*
是第一个键,因为键是字符串,并按字符串排序


为了实际使用答案,我必须在调用之前检查空列表,并使用
let(a,b)=kvp.Key,kvp.Value
Map
实现
IEnumerable
将a的输出转换为元组,这样您就可以将其视为
Seq
,如:


让findmin(map:map)=map |>Seq.minBy(fun kvp->kvp.Key)

我认为没有一个答案能够完全满足您的所有要求,但是:

  • 您可以使用
    m |>Seq.head
    访问第一个键值对。这与将地图转换为列表不同,是惰性的。这并不能保证您总是获得相同的第一个元素,但实际上,实现将保证这一点(尽管在下一个版本中可能会发生更改)

  • 为了找到最小值,实际上不需要保证
    Seq.head
    始终返回相同的元素。它只需要给你一些元素

  • 您可以使用@marklam在回答中提到的其他基于
    Seq
    的函数

  • 您还可以将
    折叠
    与类型为
    选项的状态一起使用
    ,您可以使用
    进行初始化,这样您就不必担心找到第一个元素:

    m |> Map.fold (fun st k2 v2 ->
        match st with
        | Some(k1, v1) when v1 < v2 -> st
        | _ -> Some(k2, v2)) None
    
    m>Map.fold(乐趣街k2 v2->
    匹配
    |当v1st时,一些(k1,v1)
    |部分(k2,v2))无
    

  • 这比其他答案更简单<代码>映射在内部使用AVL平衡树,因此条目已按键排序。正如@marklam
    Map
    implements
    IEnumerable
    so所述:

    let m = Map.empty.Add("Y", 2).Add("X", 1)
    let (key, value) = m |> Seq.head
    // will return ("X", 1)
    
    无论元素添加到映射中的顺序如何,
    Seq.head
    都可以直接在映射上操作,并返回最小键的键/值映射

    有时需要显式地将Map转换为Seq:

    let m = Map.empty.Add("Y", 2).Add("X", 1)
    let (key, value) = m |> Map.toSeq |> Seq.head
    

    我在本例中看到的错误消息是“类型
    'a*'b
    与类型
    Collections.Generic.KeyValuePair
    不匹配”。也可以添加类型注释而不是
    Map。toSeq

    Map是否总是有严格的顺序?@foggyinder我不知道如何回答这个问题。这些对可以无序输入,也可以订购使用,修改代码使其有序,这是我正在研究的一个途径。但你在问
    Map是否总是有一个严格的顺序
    ,正如我所理解的Map,顺序是不相关的,因为不管顺序如何,键都用来挑选一个
    键、值对
    。是什么让你相信
    Map.toSeq
    会遍历整个Map?@kvb很高兴你这么问。我原以为是的,但事实上是你在问,这说明我可能错了是否有任何官方文件表明它没有遍历整个地图?我检查了一下,但什么也没看到。对于
    toSeq
    ,state
    是否将集合视为一个可枚举的成对序列。
    但这并没有让我以这样或那样的方式保持坚定的信念。@GuyCoder-文档并不能保证这一点(但文档会怎么说?“这不会急切地遍历映射并构建新的数据结构”?),但从逻辑上讲,这是没有必要的
    Map
    s已经被排序并实现了
    seq
    ,因此
    toSeq
    必须做任何事情都是非常奇怪的
    ("/",20)
    
    let findmin (map : Map<_,_>) = map |> Seq.minBy (fun kvp -> kvp.Value)
    
    let findmin m = 
        Map.foldBack (fun k2 v2 st ->
            match st with
            | Some(k1, v1) when v1 < v2 -> st
            | _ -> Some(k2, v2)) m None
    
    m |> Map.fold (fun st k2 v2 ->
        match st with
        | Some(k1, v1) when v1 < v2 -> st
        | _ -> Some(k2, v2)) None
    
    let m = Map.empty.Add("Y", 2).Add("X", 1)
    let (key, value) = m |> Seq.head
    // will return ("X", 1)
    
    let m = Map.empty.Add("Y", 2).Add("X", 1)
    let (key, value) = m |> Map.toSeq |> Seq.head