Reputation: 2765
I have a list of type (string * (int * int)) list
. I want to be able to search through the list, finding the right element by it's string
identifier, do a calculation on one of the ints
, and then return the full, modified list.
Example:
Given a list
let st = [("a1",(100,10)); ("a2",(50,20)); ("a3",(25,40))]
I'm trying to make a function which gets one of the elements and subtracts number from one of the ints
in the tuple.
get ("a2",10) st
//Expected result: st' = [("a1",(100,10)); ("a2",(40,20)); ("a3",(25,40))]
I feel I'm almost there, but am a little stuck with the following function:
let rec get (a,k) st =
match st with
| (a',(n',p'))::rest when a'=a && k<=n' -> (n'-k,p')::rest
| (a',(n',p'))::rest -> (n',p')::get (a,k) rest
| _ -> failwith "Illegal input"
This returns [("a2",(40,20)); ("a3",(25,40))]
and is thus missing the first a1
element. Any hints?
Upvotes: 12
Views: 8941
Reputation: 45
I was looking for a function which would update an element in a list based on the element's data. I couldn't find one in F#5, so wrote one using Tomas' solution:
let updateAt (elemFindFunc: 'a -> bool) (newElem: 'a) (source: 'a list) : 'a list =
source
|> List.map
(fun elem ->
let foundElem = elemFindFunc elem
if foundElem then newElem else elem)
elemFindFunc
is the function which consumes an element and returns true
if this is the element we want to replace. If this function returns true for multiple elements, then those will be replaced by newElem
. Also, if elemFindFunc
evaluates to false
for all elements, the list will be unaltered.
newElem
is the new value you want to replace with. newElem
could be replaced by a function like valueFunc: 'a -> 'a
if you want to process the element before inserting it.
Upvotes: -1
Reputation: 243096
Lists are immutable, so if you want to "change one element" you are really creating a new list with one element transformed. The easiest way to do a transformation like this is to use List.map
function. I would write something like:
let updateElement key f st =
st |> List.map (fun (k, v) -> if k = key then k, f v else k, v)
updateElement
is a helper that takes a key, update function and an input. It returns list where the element with the given key has been transformed using the given function. For example, to increment the first number associated with a2
, you can write:
let st = [("a1",(100,10)); ("a2",(50,20)); ("a3",(25,40))]
st |> updateElement "a2" (fun (a, b) -> a + 10, b)
Upvotes: 21