相互检查列表中的每个值

发布于 2025-01-06 14:46:58 字数 304 浏览 3 评论 0原文

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

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

我的问题是如何相互检查所有单位。我尝试过使用折叠,但它让我头疼。有人可以帮我吗?

I am working with OCaml and I have a list where I need to check all elements in a list with each other. The list is a list of units, either base or derived units. Base units are m,s,g and derived units are any units that use m,s,g such as kg, min, ft, lb, etc.

So an example list would be [lb; ft; m]. This list would be invalid because ft and m share the same base unit: m. To be more clear [lb; kg; s] will be invalid because lb and kg share the same base unit:m. However [ft; s; m] is completely valid. These base unit conversions are kept in a hash for lookup.

My problem is how could I check all the units with each other. I've tried using folds but it's making my head hurt. Can anyone help me out?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

阳光的暖冬 2025-01-13 14:46:59

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

(* [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 ,所以折叠,但然后你想要快捷方式早期失败语义...)并且我没有看到任何优势。

The simple solution with quadratic complexity:

(* [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

Remark that the inner check_rest is only checking a predicate on each element of the list. That's 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

You could go combinator-crazy and also implement check_each_pair as a call to a recursion combinator, but that's not direct (you need to accumulate rest somehow, so a fold, but then you want the shortcut fail-early semantics...) and I don't see any advantage.

昨迟人 2025-01-13 14:46:59

一个简单的解决方案是首先从列表中创建所有对的列表(通过使用 笛卡尔积列表及其自身)并稍后检查对列表上的条件:

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)

A simple solution is to create a list of all pairs from a list first (by using cartesian product of the list with itself) and check the condition on the list of pairs later:

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文