'Filter custom object array based on another array of type int in f#
I have two arrays in f# 1st Array is called CompositionArray containing an array of objects of type Composition.KeyValue 2nd Array is just an integer array containing some indexes. Ex: [10; 20; 30]
I have to filter/knock out CompositionArray based on the indexes found in 2nd Array. So the final filtered array would not contain the objects for 10th, 20th and 30th indexes.
Below is what I tried so far but getting a compile error
The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to mutate a value, then mark the value 'mutable' and use the '<-' operator e.g. 'exists <- expression'.
let finalCompositions = [|
if ArrayIndexes.Length > 0 then //if there are elements in IndexArray then only filter CompositionArray
for i = 0 to CompositionArray.Length-1 do //iterate through the composition array
for y = 0 to IndexeArray.Length-1 do //iterate through the index array
let exists = false
if i <> IndexArray.[y] then //CompositionArray loop counter not equals to IndexArray value
if y.Equals(IndexArray.Length-1) && not exists then //Considering this is end of IndexArray counter
yield CompositionArray.[i]
else
exists = true //Compile error at this line.
else
for i = 0 to CompositionArray.Length-1 do
yield CompositionArray.[i] //Return the entire CompositionArray as is if there are no elements in IndexArray
|]
I am new to f# and sorry for asking such a newbie question
Solution 1:[1]
let removeAt index input =
input
|> List.mapi (fun i el -> (i <> index, el))
|> List.filter fst |> List.map snd
let folder (numRemovals, filtered) index =
let i = index - numRemovals
numRemovals + 1, filtered |> removeAt i
let compArray = [ 0..31 ] // Example; can be any type
let indices = [10; 20; 30]
let result =
indices
|> List.fold folder (0, compArray)
|> snd
// result = [0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 11; 12; 13; 14; 15; 16; 17; 18; 19;21; 22; 23;24; 25; 26; 27; 28; 29; 31]
Solution 2:[2]
Function to produce lazy sequence from any source. It allocates far less than version with lists.
let removeAtIndexes (source: 'a seq) (indexes: int seq) : 'a seq =
seq {
let set = HashSet indexes
for (el, idx) in Seq.zip source (Seq.initInfinite id) do
if not <| set.Contains idx then
yield el
}
let compAr = [ 0..31 ]
let indices = [10; 20; 30]
let result = removeAtIndexes compAr indices
printfn "%s" (String.Join(", ", result))
If you need to produce list, use result |> List.ofSeq.
If method allocates too much, change index tracking to mutable variable.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | JL0PD |
