0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

List.minByの挙動がわからぬ

Last updated at Posted at 2019-12-27

どうにもminByの挙動が不可解。
僕の理解が浅いだけなのか、それともissue投げるべきバグなのかがわからない・・・。

2019/12/27
バグじゃなくてそもそも使い方おかしいよ教えて頂きました!(コメント欄参照)
僕の使い方がおかしいだけでしたね:tired_face:
本当にありがとうございます!

対象のリスト

// トランプのカード
type Card = 
  {
    // 値
    Number : int
    // 柄
    Suit : string
    // 表示上の数値(A,J,Q,K用)
    Write : string
  }

// ジョーカーを除くトランプの集合体を作る
let makeSuitCards suit = 
  [ for i in 1..13 -> 
    {
        Number = i;
        Suit = suit;
        Write = 
          match i with 
            | 1  -> "A"
            | 11 -> "J"
            | 12 -> "Q"
            | 13 -> "K"
            | _ -> i.ToString()
    }]

let makeDeck = makeSuitCards "H" @ makeSuitCards "C" @ makeSuitCards "S" @ makeSuitCards "D"
let cards = makeDeck

minByする

minBy試す
// 最小値を取る、条件付き -> Cの1が取れるはずなんだが・・・
cards |> List.minBy(fun elm -> elm.Number = (List.min cards).Number && elm.Suit = "C" ) |> printfn "%A"

↓↓↓

実行結果
{Number = 13;
 Suit = D;
 Write = K}

!?
なんか想定と違うものが返ってきた。

maxByだと

maxByでやってみる
// C1が取れるよね
cards |> List.maxBy(fun elm -> elm.Number = (List.min cards).Number && elm.Suit = "C" ) |> printfn "%A"

↓↓↓

実行結果
{Number = 1;
 Suit = C;
 Write = A}

意図通り取れるんだよなぁ。

複数条件なのが悪い?

Numberだけ指定してみる
// Number=2を指定してるけどやっぱりminByだと取れない
cards |> List.minBy(fun elm -> elm.Number = 2 ) |> printfn "%A"
cards |> List.maxBy(fun elm -> elm.Number = 2 ) |> printfn "%A"

↓↓↓

実行結果
{Number = 13;
 Suit = D;
 Write = K}
{Number = 2;
 Suit = H;
 Write = 2}
Suitだけ指定してみる
// Suit="C"を指定してるけどやっぱりminByだと取れない
cards |> List.minBy(fun elm -> elm.Suit = "C" ) |> printfn "%A"
cards |> List.maxBy(fun elm -> elm.Suit = "C" ) |> printfn "%A"

↓↓↓

実行結果
{Number = 13;
 Suit = D;
 Write = K}
{Number = 1;
 Suit = C;
 Write = A}

やっぱりmaxByはちゃんと絞れるけどminByは絞れてない感じ。
なんでやねん( ;∀;)

公式リポジトリらしきところで実装見ても、変な事してるようには見えないんだけどなぁ
https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/list.fs

fsharp/list.fsから抜粋
        [<CompiledName("MinBy")>]
        let inline minBy projection (list:list<_>) =
            match list with 
            | [] -> invalidArg "list" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString
            | h::t ->
                let mutable acc = h
                let mutable accv = projection h
                for x in t do
                    let currv = projection x
                    if currv < accv then
                        acc <- x
                        accv <- currv
                acc


        [<CompiledName("MaxBy")>]
        let inline maxBy projection (list:list<_>) =
            match list with 
            | [] -> invalidArg "list" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString
            | h::t ->
                let mutable acc = h
                let mutable accv = projection h
                for x in t do
                    let currv = projection x
                    if currv > accv then
                        acc <- x
                        accv <- currv
                acc
0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?