У меня есть список, и я хочу удалить элемент, соответствующий некоторым критериям, но удалить только один элемент.
let items = [1;2;3]
let predicate x =
x >= 2
let result = items |> List.fold ...
// result = [1;3]
Как добиться возврата метода методом с [1; 3]?
4 ответа
Вы можете использовать универсальную рекурсивную функцию
let rec removeFirst predicate = function
| [] -> []
| h :: t when predicate h -> t
| h :: t -> h :: removeFirst predicate t
Или хвостовой рекурсивный (если вы боитесь переполнения стека)
let removeFirst predicate list =
let rec loop acc = function
| [] -> List.rev acc
| h :: t when predicate h -> (List.rev acc) @ t
| h :: t -> loop (h :: acc) t
loop [] list
let result =
items
|>List.scan (fun (removed, _) item ->
if removed then true, Some(item) //If already removed, just propagate
elif predicate item then true, None //If not removed but predicate matches, don't propagate
else false, Some(item)) //If not removed and predicate doesn't match, propagate
(false, None)
|>List.choose snd
Государство кортеж. Первый элемент - это логический флаг, указывающий, удалили ли мы уже какой-либо элемент из списка. Второй элемент - это опция: некоторые, когда мы хотим испустить элемент, в противном случае - None.
Последняя строка берет вторые элементы из состояний и для каждого из них выдает обернутое значение (в случае Some) или ничего не делает (в случае None).
Стремление к интуитивному решению.
let removeAt index list =
let left, right = List.splitAt index list
left @ (List.skip 1 right)
let removeFirst predicate list =
match List.tryFindIndex predicate list with
| Some index -> removeAt index list
| None -> list
Для исполнения (длинные списки).
let removeFirst predicate list =
let rec finish acc rem =
match rem with
| [] -> acc
| x::xs -> finish (x::acc) xs
and find l p acc rem =
match rem with
| [] -> l
| x::xs ->
if p x then finish xs acc
else find l p (x::acc) xs
find list predicate [] list
Вот короткая альтернатива, которая в моем тестировании была быстрее, чем другие, предложенные до сих пор:
let removeFirst p xs =
match List.tryFindIndex p xs with
| Some i -> List.take i xs @ List.skip (i+1) xs
| None -> xs
Похожие вопросы
Новые вопросы
filter
Программа или процедура, которая блокирует доступ к данным, которые соответствуют определенному критерию. Примером может служить «веб-фильтр», который отсеивает сайты для взрослых. НЕ используйте этот тег для: фильтров сервлетов Java. Используйте вместо этого [servlet-filters]. Для фильтров Bloom используйте вместо этого [bloom-filter]. Для CSS-фильтров используйте [css-filters].