2015-11-04 13 views
5

Devo scrivere un programma che fornisca in uscita una tupla con: min e max di una lista non vuota e il valore che appare più spesso. In particolare:Elemento min/max e più frequente di una lista

min_max [1;0;-1;2;0;-4] ==> (-4; 2) 
min_max: int list -> (int * int) 

mode [-1;2;1;2;5;-1;5;5;2] ==> 2 
mode: int list -> int 

Questo è il codice che ho scritto per max (min è quasi uguale), ma come posso fare per ricevere come output una tupla con due valori?

let rec max_list xs = 
    match xs with 
    | [] -> failwith "xs" "Empty list" 
    | [x] -> x 
    | x1::x2::xs' -> max_list((max2 x1 x2)::xs');; 
+0

Come nota a margine; il tuo 'max_list' sembra un po 'complicato per il suo scopo; potrebbe essere più semplice passare il massimo corrente al resto della lista e aggiornarlo se la testa attuale è maggiore. o senza passarlo in giro; basta restituire il massimo tra la testa attuale e la max_list della coda – Sehnsucht

risposta

2
let minMax xs = 
    xs 
    |> List.fold 
     (fun (mn, mx) i -> min mn i, max mx i) 
     (System.Int32.MaxValue, System.Int32.MinValue) 

Non particolarmente efficiente, ma divertente da scrivere:

let mode xs = 
    xs 
    |> List.groupBy id 
    |> List.map (fun (i, is) -> i, Seq.length is) 
    |> List.maxBy snd 
    |> fst 
+0

Perché non utilizzare un BAG immediatamente, senza una mappa? (List.maxBy (fun (_, x) -> Seq.length x)) –

+1

@ FoggyFinder Nessun motivo particolare :) –

+0

Perché non posso usare alcuna funzione al di fuori di quanto è stato spiegato dal professore: e questo è il mio problema quando devo fare esercizi, perché anche in questo caso ho pensato subito a lis.map, list.fold, seq.fold ecc. –

3

prenderò il primo suggerimento dalla risposta @Mark Seemann s' e correre con esso, in modo da renderla generica, lavorare con qualsiasi tipo di raccolta e gestire sensibilmente il caso della collezione vuota.

let tryMinMax xs = 
    Seq.fold (function 
    | Some(mn, mx) -> fun i -> Some(min mn i, max mx i) 
    | None   -> fun i -> Some(i, i)) None xs 

[1;0;-1;2;0;-4] 
|> tryMinMax 
// val it : (int * int) option = Some (-4, 2) 

Per la più frequente parte della domanda:

let mostFrequent xs = 
    xs 
    |> Seq.countBy id 
    |> Seq.maxBy snd 
    |> fst 

[1;0;-1;2;0;-4] 
|> mostFrequent 
// val it : int = 0 
0

opzione senza l'uso di moduli standard:

open System 
let tryMinMax xs = 
    let rec minMax xs mn mx = 
     match xs with | [] -> mn, mx | h::t -> minMax t (min mn h) (max mx h) 
    match xs with | [] -> None | _ -> Some(minMax xs Int32.MaxValue Int32.MinValue) 

dotnetfiddle

Quanto alla seconda questione - mostrare i loro tentativi di risolvere.

Problemi correlati