Существует ли более идиоматичное разделение игл OCaml из реализации стога сена?

#php #ocaml #partitioning

Вопрос:

Я обнаружил, что периодически переписываю эти (или аналогичные) функции. Интересно, есть ли у stdlib более идиоматическое решение? Как показано ниже, я решил использовать containers библиотеку для некоторых функций, но подозреваю, что набор инструментов по умолчанию также может обладать достаточными, чистыми возможностями.

Для всех x в X удалите/разделите первое вхождение x из Y.

Ниже показана exn реализация без ограничений.

Примеры:

 extract [1] [2;1;3]
;; ([1], [], [2;3])

extract [2;4] [2;1;3;4]
;; ([2;4], [], [1;3])

extract [5] [1;2;3]
;; ([], [5], [1;2;3])

extract [1;1;9] [2;3;1;4;1;5;1]
;; ([1;1], [9], [2;3;4;5;1])
 

Допущения:

  • X amp; Y и не правильные наборы, а связанные коллекции (например, список, массив)
  • коллекции неупорядочены

Реализация:

 (* Given needles and haystack lists, extract needles elements from haystack.
  Produce (successfully_extracted, unsuccessfully_extracted, remaining_haystack) *)
let extract needles haystack =
  let open CCList in
  let f (extracted, needles', haystack') curr =
    match find_idx (Int.equal curr) needles' with
    | Some (idx, v) -> (v :: extracted, remove_at_idx idx needles', haystack')
    | _ -> (extracted, needles', curr :: haystack')
  in
  fold_left f ([], needles, []) haystack |> fun (a, b, c) -> (a, b, rev c)
 

Комментарии:

1. Эта функция выглядит для меня очень специфичной и нишевой. И я никогда лично не реализовывал ничего близкого к этому, честно говоря. Поэтому меня не удивляет, что ничего подобного не существует ни в стандартной библиотеке, ни в ее расширениях, таких как Ядро или контейнеры. Можете ли вы поделиться своими историями пользователей? Например, когда и почему вам могут понадобиться такие селекторы, возможно, существует более естественный способ кодирования ваших проблем.

2. Конечно! Мне нужно вытащить иголки из стога сена. У меня есть ведро вещей (представляющих физические или виртуальные инвестиции), и я получаю заказ. Этот порядок вещей следует извлечь из инвентаря стога сена. В стоге сена может быть несколько копий чего-либо, например, на полке магазина есть N виджетов в инвентаре, а заказ запрашивает только N-1 виджетов, поэтому в следующем стоге сена останется 1 виджет. Возможно, чего-то нет в наличии-я хочу знать, какой заказ не может быть выполнен. Возможно, предпочтительнее преобразовать в тип карты, а затем обратно, но мои списки известны небольшими.

3. Не лучше ли было бы представлять доступность каждого виджета с помощью номера, а не дублировать его? Например, когда в моем магазине сто клавиатур, я бы, вероятно, представил их как один товар с наличием 100 наименований.

Ответ №1:

Эй, я не уверен, хорошо ли я понял твою проблему, но, может быть, это решит ее :

 let rec pop popL l = 
match popL with 
| [] -> l
| e :: es -> begin
match l with 
| x :: xs when x = e -> pop es xs
| x :: xs -> x :: pop popL xs
| [] -> []
end;;