2012-05-29 2 views
3

Я объявила переменную al : 'a list, функцию a_to_b : 'a -> 'b и функцию score : 'b -> int. Затем let bl = List.map a_to_b al in ... в следующем коде определяет bl : 'b list.Определить тип 2 соответствующих наборов

let find_best (bl : 'b list) : 'b = 
    let score_best, b_best = List.fold_left 
    (fun (score_old, b_old) b_new -> 
     let score_new = score b_new in 
     if score_old < score_new then 
      (score_new, b_new) else 
      (score_old, b_old)) 
    (score (List.hd bl), List.hd bl) bl in 
    b_best 

let bl = List.map a_to_b al in 
find_best bl 

Этот фрагмент кода находит b_best таким образом, что его score является наибольшей. Но одна из моих потребностей - это то, что я также хочу знать, что a_best генерирует это b_best через a_to_b, и нет способа. Например, если b_best является 4-м элементом в bl, я считаю, что 4-й элит из al - это то, что я хочу получить.

Я не хочу добавлять дополнительные параметры к функции find_best. Мой вопрос заключается в том, есть ли обычный способ определить тип al и bl, чтобы упростить отслеживание a_best от b_best, например, используя array вместо list? или конвертировать в array, а затем конвертировать в list назад?

+0

Кстати, правильное имя функции 'find_best' было бы' argmax': http://en.wikipedia.org/wiki/Arg_max –

ответ

3

Вы можете сделать что-то подобное:

let abl = List.combine bl al in (* ('b * 'a) list *) 
let a_best = List.assoc b_best abl (* returns the value associated to b_best *) 
+0

Это, конечно, предполагает, что тип 'b' поддерживает' = '. «List.assq» может быть лучшим вариантом (а также чуть быстрее). –

2

Во многих ситуациях я бы просто определить b_best взять список пар и возвращает пару. Было бы полиморфный во второй элемент пары:

let find_best (bl : ('b * 'a) list) : 'b * 'a = 
    let score_best, ba_best = List.fold_left 
    (fun (score_old, (b_old, a_old)) (b_new, a_new) -> 
     let score_new = score b_new in 
     if score_old < score_new then 
      (score_new, (b_new, a_new)) else 
      (score_old, (b_old, a_old))) 
    (score (List.hd bl), List.hd bl) bl in 
    ba_best 

(. Или вы могли бы определить его принять два списка, но это, кажется, даже меньше, как то, что вы просите)

Под ограничениями, которые вы указываете, find_best не имеет доступа к al, поэтому вам кажется, что вам нужно вернуть индекс и затем использовать List.nth, чтобы получить значение от al. Если вам нужно сделать это много с длинными списками, List.nth может быть слишком медленным, и поэтому вы можете использовать массив для al.