检查列表中的每个值

时间:2012-02-17 01:53:23

标签: algorithm list ocaml ml

我正在使用OCaml,我有一个列表,我需要相互检查列表中的所有元素。该列表是单位列表,基本单位或派生单位。基本单位是m,s,g,派生单位是使用m,s,g的任何单位,如kg,min,ft,lb等。

所以一个示例列表将是[lb;英尺;米]。此列表无效,因为ft和m共享相同的基本单位:m。更清楚[lb;公斤; s]将无效,因为lb和kg共享相同的基本单位:m。然而[ft; S; m]完全有效。这些基本单位转换保存在哈希中以供查找。

我的问题是如何相互检查所有单位。我尝试过使用褶皱,但它会让我的头部受伤。任何人都可以帮助我吗?

2 个答案:

答案 0 :(得分:2)

具有二次复杂度的简单解决方案:

(* [check_pair] should return [false] if check fails *)
let rec check_each_pair check_pair = function
  | [] -> true
  | hd1 :: rest ->
    let rec check_rest = function
      | [] -> true
      | hd2 :: rest -> check_pair hd1 hd2 && check_rest rest
    in
    check_rest rest && check_each_pair check_pair rest

注意内部check_rest仅检查列表中每个元素的谓词。那是List.for_all

let rec check_each_pair check_pair = function
  | [] -> true
  | hd1 :: rest ->
    List.for_all (check_pair hd1) rest && check_each_pair check_pair rest

你可以去组合疯狂,也可以实现check_each_pair作为对递归组合的调用,但这不是直接的(你需要以某种方式累积rest,所以折叠,但是你想要快捷方式失败 - 早期语义......)我没有看到任何优势。

答案 1 :(得分:1)

一个简单的解决方案是首先从列表中创建所有对的列表(通过使用列表中的cartesian product)并稍后检查对列表中的条件:

let cartesian xs ys =
    List.concat (List.map (fun x -> List.map (fun y -> (x, y)) ys) xs)

let haveDifferentBases(x, x') =
   (* check whether they have different base units *)

let check_all_pairs xs =
   List.for_all haveDifferentBases (cartesian xs xs)