I need to pack data like this:
let data = [1; 2; 2; 3; 2; 2; 2; 4]
let packed = [(1, 1); (2, 2); (3, 1); (2, 3); (4, 1)]
Where each item say how much times it exist before the next. However, it must work with non-adjacent duplications.
I can work this with classical imperative code, but wonder how do this functionally.
Also, Seq.countBy not work because it take in account all the values
If you already have an imperative version, you can follow a set of small steps to refector to a recursive implementation.
Recursion
While I don't know what your imperative version looks like, here's a recursive version:
let pack xs =
let rec imp acc = function
| [] -> acc
| h::t ->
match acc with
| [] -> imp [(h, 1)] t
| (i, count) :: ta ->
if h = i
then imp ((i, count + 1) :: ta) t
else imp ((h, 1) :: (i, count) :: ta) t
xs |> imp [] |> List.rev
This function has the type 'a list -> ('a * int) list when 'a : equality. It uses a private 'implementation function' called imp to do the work. This function is recursive, and threads an accumulator (called acc) throughout. This accumulator is the result list, having the type ('a * int) list.
If the accumulator list is empty, the head of the original list (h), as well as the count 1, is created as a tuple as the only element of the updated accumulator, and the imp function is recursively called with that updated accumulator.
If the accumulator already contains at least one element, the element is extracted via pattern matching, and the element in that tuple (i) is compared to h. If h = i, the accumulator is updated; otherwise, a new tuple is consed on acc. In both cases, though, imp is recursively called with the new accumulator.
You can call it with a list equivalent to your original tuple like this:
> pack [1; 2; 2; 3; 2; 2; 2; 4];;
val it : (int * int) list = [(1, 1); (2, 2); (3, 1); (2, 3); (4, 1)]
Fold
Once you have a recursive version, you often have the recipe for a version using a fold. In this case, since the above pack function has to reverse the accumulator in the end (using List.rev), a right fold is most appropriate. In F#, this is done with the built-in List.foldBack function:
let pack' xs =
let imp x = function
| (i, count) :: ta when i = x -> (i, count + 1) :: ta
| ta -> (x, 1) :: ta
List.foldBack imp xs []
In this case, the function passed to List.foldBack is a bit too complex to pass as an anonymous function, so I chose to define it as a private inner function. It's equivalent to the recursive imp function used by the above pack function, but you'll notive that it doesn't have to call itself recursively. Instead, it just has to return the new value for the accumulator.
The result is the same:
> pack' [1; 2; 2; 3; 2; 2; 2; 4];;
val it : (int * int) list = [(1, 1); (2, 2); (3, 1); (2, 3); (4, 1)]
My solution assumes the data collection is a list. If having it as a tuple (as per your example) was intentional then for my solution to work the tuple has to be converted to a list (an example how to do it can be found here).
let groupFunc list =
let rec groupFuncRec acc lst init count =
match lst with
| [] -> List.rev acc
| head::[] when head = init
-> groupFuncRec ((init, count)::acc) [] 0 0
| head::[] when head <> init
-> groupFuncRec ((head, 1)::acc) [] 0 0
| head::tail when head = init
-> groupFuncRec acc tail head (count+1)
| head::tail when head <> init
-> groupFuncRec ((init, count)::acc) tail head 1
let t = List.tail list
let h = List.head list
groupFuncRec [] t h 1
When I run the function on your sample data I get back the expected result:
list = [(1, 1); (2, 2); (3, 1); (4, 1)]
You can get Seq.countBy to work by including some positional information in its argument. Of course, you need then to map back to your original data.
[1; 2; 2; 3; 2; 2; 2; 4]
|> Seq.scan (fun (s, i) x ->
match s with
| Some p when p = x -> Some x, i
| _ -> Some x, i + 1 ) (None, 0)
|> Seq.countBy id
|> Seq.choose (function
| (Some t, _), n -> Some(t, n)
| _ -> None )
|> Seq.toList
// val it : (int * int) list = [(1, 1); (2, 2); (3, 1); (2, 3); (4, 1)]
Related
I have a solution to this, and several working-but-unsatisfactory solutions, but it took a lot of work and seems unnecessarily complex.
Am I missing something in F#?
The Problem
I have a sequence of numbers
let nums = seq { 9; 12; 4; 17; 9; 7; 13; }
I want to decorate each number with an "index", so the result is
seq [(9, 0); (12, 1); (4, 2); (17, 3); ...]
Looks simple!
In practice the input can be very large and of indeterminate size. In my application, it is coming from a REST service.
Further
the operation must support lazy evaluation (because of the REST backend)
must be purely functional, which eliminates the obvious seq { let mutable i = o; for num in nums do .. } solution, ditto for while ... do ...
Lets call the function decorate, of type (seq<'a> -> seq<'a * int>), so it would work as follows:
nums
|> decorate
|> Seq.iter (fun (n,index) -> printfn "%d: %d" index n)
Producing:
0: 9
1: 12
2: 4
...
6: 13
This is a trivial problem with Lists (apart from the lazy evaluation), but tricky with Sequences.
My solution is to use Seq.unfold, as follows:
let decorate numSeq =
(0,numSeq)
|> Seq.unfold
(fun (count,(nums : int seq)) ->
if Seq.isEmpty nums then
None
else
let result = ((Seq.head nums),count)
let remaining = Seq.tail nums
Some( result, (count+1,remaining)))
This meets all requirements, and is the best I've come up with.
Here's the whole solution, with diagnostics to show lazy evaluation:
let nums =
seq {
// With diagnostic
let getN n =
printfn "get: %d" n
n
getN 9;
getN 12;
getN 4;
getN 17;
getN 9;
getN 7;
getN 13
}
let decorate numSeq =
(0,numSeq)
|> Seq.unfold
(fun (count,(nums : int seq)) ->
if Seq.isEmpty nums then
None
else
let result = ((Seq.head nums),count)
let remaining = Seq.tail nums
printfn "unfold: %A" result
Some( result, (count+1,remaining)))
nums
|> Seq.cache
// To prevent re-computation of the sequence.
// Will be necessary for any solution. This solution required only one.
|> decorate
|> Seq.iter (fun (n,index) -> printfn "ITEM %d: %d" index n)
PROBLEM: This took a LOT of work to reach. It looks complex, compared to the (apparently) simple requirement.
QUESTION: Is there a simpler solution?
Discussion of some alternatives.
All work, but are unsatisfactory for the reasons given
// Most likely: Seq.mapFold
// Fails lazy evalation. The final state must be evaluated, even if not used
let decorate numSeq =
numSeq
|> Seq.mapFold
(fun count num ->
let result = (num,count)
printfn "yield: %A" result
(result,(count + 1)))
0
|> fun (nums,finalState) -> nums // And, no, using "_" doesn't fix it!
// 'for' loop, with MUTABLE
// Lazy evaluation works
// Not extensible, as the state 'count' is specific to this problem
let decorate numSeq =
let mutable count = 0
seq {
for num in numSeq do
let result = num,count
printfn "yield: %A" result
yield result;
count <- count+1
}
// 'for' loop, without mutable
// Fails lazy evaluation, and is ugly
let decorate numSeq =
seq {
for index in 0..((Seq.length numSeq) - 1) do
let result = ((Seq.item index numSeq), // Ugly!
index)
printfn "yield: %A" result
yield result
}
// "List" like recursive descent,
// Fails lazy evaluation. Ugly, because we are not meant to use recursion on Sequences
// https://stackoverflow.com/questions/11451727/recursive-functions-for-sequences-in-f
let rec decorate' count (nums : int seq) =
if Seq.isEmpty nums then
Seq.empty
else
let hd = Seq.head nums
let tl = Seq.tail nums
let result = (hd,count)
let tl' = decorate' (count+1) tl
printfn "yield: %A" result
seq { yield result; yield! tl'}
let decorate : (seq<'a> -> seq<'a * int>) = decorate' 0
You can use Seq.mapi to do what you need.
let nums = seq { 9; 12; 4; 17; 9; 7; 13; }
nums |> Seq.mapi (fun i num -> (num, i))
This gives (9, 0); (12, 1); etc...
Seq is "lazy" in the same sense as IEnumerable in C#.
You can read about Seq.mapi here:
https://fsharp.github.io/fsharp-core-docs/reference/fsharp-collections-seqmodule.html#mapi
Read more about the use of map here:
https://fsharpforfunandprofit.com/posts/elevated-world/#map
In addition to the Seq.mapi function mentioned in Sean's answer, F# also has a built-in Seq.indexed function, which decorates a sequence with index. This does not do exactly what you're asking, because the index becomes the first element of the tuple, but depending on your use case, it may do the trick:
> let nums = seq { 9; 12; 4; 17; 9; 7; 13; };;
val nums : seq<int>
> Seq.indexed nums;;
val it : seq<int * int> = seq [(0, 9); (1, 12); (2, 4); (3, 17); ...]
If I was trying to implement this on my own using a more primitive function, it could be done using Seq.scan, which is a bit like fold but produces a lazy sequence of states. The only tricky thing is that you have to construct the initial state and then process the rest of the sequence:
Seq.tail nums
|> Seq.scan (fun (prevIndex, _) v -> (prevIndex+1, v)) (0, Seq.head nums)
This will not work for empty lists, even though the function should logically be able to handle this.
Using for is not bad, or wrong. for and yield in a seq {} is how you write new seq functions, if none of the provided functions in Seq Module is a best-fit. It is neither wrong, or bad to use this special construct. It's the same as C# foreach and yield syntax.
Using a mutable in a limited scope, is also not wrong. Mutables are a bad idea, if they escape the scope. For example, you return a mutable value, from a function.
Its important to put the mutable inside the seq, and not outside. Your version is wrong.
Let's assume this
let xs = decorate [3;6;7;12;9]
for x in xs do
printfn "%A" x
for x in xs do
printfn "%A" x
Now you have two versions of decorate. The first version
let decorate numSeq =
let mutable count = 0
seq {
for num in numSeq do
yield (num,count)
count <- count + 1
}
will print:
(3, 0)
(6, 1)
(7, 2)
(12, 3)
(9, 4)
(3, 5)
(6, 6)
(7, 7)
(12, 8)
(9, 9)
Or in other words. The mutable is shared across all invocation whenever you iterate through the sequence. As a general tip. If you want to return a seq then put all your code into seq. And put the seq {} after the = sign. If you do this instead.
let decorate numSeq = seq {
let mutable count = 0
for num in numSeq do
yield (num,count)
count <- count + 1
}
you get the correct output:
(3, 0)
(6, 1)
(7, 2)
(12, 3)
(9, 4)
(3, 0)
(6, 1)
(7, 2)
(12, 3)
(9, 4)
Forther you explain, that this version is not "extensible". But the version with mapi you select as "correct". Has the same problem, it only provides an index, nothing more.
If you want a more generic version, you always can make a function that expects its values as a function argument. You could for example change the above function to this code.
let decorate2 f (state:'State) (xs:'T seq) = seq {
let mutable state = state
for x in xs do
yield state, x
let newState = f state x
state <- newState
}
Now decorate2 expects a state that you can freely pass, and a function to change the state. With this function you could then write:
decorate2 (fun state _ -> state+1) 0 [3;6;7;12;9]
The function signature is nearly the same as Seq.scan, but still a little bit different. But if you want to create a indexed function, you could use scan like this.
let indexed xs =
Seq.scan (fun (count,_) x -> (count+1,x)) (0,Seq.head xs) (Seq.skip 1 xs)
Just in my opinion. This version is harder rot read, understand, and just fugly compared to decorate or decorate2.
And just a note. There is already a Seq.indexed function in the standard library, that does what you wish.
for x in Seq.indexed [3;6;7;12;9] do
printfn "%A" x
will print
(0, 3)
(1, 6)
(2, 7)
(3, 12)
(4, 9)
Let's say I have an array
let arr = [|1;2;3;4;5;6|]
I would like to convert it to something like
[|(1,2);(3,4);(5,6)|]
I've seen Seq.window but this one is going to generate something like
[|(1,2);(2,3);(3,4);(4,5);(5,6)|]
which is not what I want
You can use Array.chunkBySize and then map each sub-array into tuples:
let input = [|1..10|]
Array.chunkBySize 2 list |> Array.map (fun xs -> (xs.[0], xs.[1]))
#Slugart's accepted answer is the best approach (IMO) assuming you know that the array has an even number of elements, but here's another approach that doesn't throw an exception if there does happen to be an odd number (it just omits the last trailing element):
let arr = [|1;2;3;4;5|]
seq { for i in 0 .. 2 .. arr.Length - 2 -> (arr.[i], arr.[i+1]) } |> Seq.toArray
You could use Seq.pairwise, as long as you filter out every other tuple. The filtering needs to pass a state through the iteration, which is usually effected by the scan function.
[|1..10|]
|> Seq.pairwise
|> Seq.scan (fun s t ->
match s with None -> Some t | _ -> None )
None
|> Seq.choose id
|> Seq.toArray
// val it : (int * int) [] = [|(1, 2); (3, 4); (5, 6); (7, 8); (9, 10)|]
But then it's also possible to have scan generate the tuples directly, on penalty of an intermediate array.
[|1..10|]
|> Array.scan (function
| Some x, _ -> fun y -> None, Some(x, y)
| _ -> fun x -> Some x, None )
(None, None)
|> Array.choose snd
Use Seq.pairwise to turn a sequence into tuples
[|1;2;3;4;5;6|]
|> Seq.pairwise
|> Seq.toArray
val it : (int * int) [] = [|(1, 2); (2, 3); (3, 4); (4, 5); (5, 6)|]
Should be:
let rec slice =
function
| [] -> []
| a::b::rest -> (a,b) :: slice (rest)
| _::[] -> failwith "cannot slice uneven list"
Let's say I have this array:
let reportStructure = [|(2, 1); (3, 2); (4, 2); (5, 3); (6, 4); (7, 3)|]
where the first int in a tuple reports to the second int.
I can map that really easily with
let orgMap = Map.ofArray reporting
From there, I could easily get a list of all the ints that report to 2 with
orgMap
|> Map.filter (fun _ key -> key = 2)
which returns
map [(3, 2); (4, 2)]
What I'd really like to see, however, is the entire structure, from 2 all the way down. For example, I'd like to find a way that could give me the sample output
map [(3, 2); (4, 2); (5, 3); (6, 4); (7, 3)]
if I'm looking for person 2 or
map [(5, 3); (7, 3)]
if I'm interested in person 3.
Can I do this? If so, how? Is there another structure other than a map that would be a better way to make this happen?
Thanks in advance for your help.
Since OCaml is close to F# and trying to find Topological sort in F# was not turning up anything useful I looked for OCaml code.
I found An Introduction to Objective Caml which had a solution to your problem using Depth First Search and used it as the basis for this answer. Also because you are new to F# you can review the document and see how the code is derived. Oddly I took a look at the remainder of the document after posting this and he has a more advanced version of DFS latter in the document.
Your input is an array [| |] but your answer is a list [] so I did most of the work as list.
The answers are not in the same order as you had, but they are in the same format.
let reportStructure = [|(2, 1); (3, 2); (4, 2); (5, 3); (6, 4); (7, 3)|]
//
// 6 -> 4 -> 2
// 5 -> 3 -> 2 -> 1
// 7 -> 3
// val revStructure : tl:('a * 'b) list -> ('b * 'a) list
let revStructure tl = List.map (fun (a,b) -> (b,a)) tl
// val mem : item:'a -> list:'a list -> bool when 'a : equality
let mem item list = List.exists (fun x -> x = item) list
// val successors : n:'a -> edges:('a * 'b) list -> 'b list when 'a : equality
let successors n edges =
let matching (s,_) = s = n
List.map snd (List.filter matching edges)
// val dist : pred:'a -> succs:'b list -> ('a * 'b) list
let dist pred succs = List.map (fun y -> (pred,y)) succs
// val dfsPairs : edges:('a * 'a) list -> start:'a -> ('a * 'a) list when 'a : equality
let dfsPairs edges start =
let rec dfsPairsInner edges visited start result =
match start with
| [] -> List.rev (revStructure result)
| n::nodes ->
if mem n visited then
dfsPairsInner edges visited nodes result
else
let predecessors = dist n (successors n edges)
let result =
match predecessors with
| [] -> result
| _ -> predecessors # result
dfsPairsInner edges (n::visited) ((successors n edges) # nodes) result
dfsPairsInner edges [] [start] []
let revEdges = revStructure (List.ofArray reportStructure)
let result = dfsPairs revEdges 2
// val result : (int * int) list = [(4, 2); (3, 2); (7, 3); (5, 3); (6, 4)]
let result = dfsPairs revEdges 3
// val result : (int * int) list = [(7, 3); (5, 3)]
I assume that you want to get a list of pair of ints with "numbers" that directly or indirectly report to some "root".
Here is an easy but inefficient solution:
let reportStructure = [|(2, 1); (3, 2); (4, 2); (5, 3); (6, 4); (7, 3)|]
let reportStructureSet =
reportStructure |> Set.ofArray
let reportingDirectlyTo root raportsToSet =
raportsToSet
|> Set.filter(fun (_, key) -> key = root)
let addNextGeneration previousIteration raportsToSet =
let numbersLowerInHierarchy = previousIteration |> Set.map fst
raportsToSet |> Set.filter(
// select only those elements from raportsToSet...
fun (num, supervisor) ->
// ...which either are already in previousIteration
(Set.contains (num, supervisor) previousIteration) ||
// ...or are "below" someone from previousIteration
(Set.contains supervisor numbersLowerInHierarchy))
let reportingDirectlyOrIndirectlyTo root raportsToSet =
// applies addNextGeneration until is "stabilizes" on some value
let rec fixPointHelper previousIteration =
let nextIteration = addNextGeneration previousIteration raportsToSet
if nextIteration = previousIteration
then nextIteration
else fixPointHelper nextIteration
// set of numbers directly reporting to root
let reportsDirectly = reportingDirectlyTo root raportsToSet
// start "iteration" using numbers directly reporting to root
fixPointHelper reportsDirectly
let reportingDirectlyOrIndirectlyToList root raportsToSet =
reportingDirectlyOrIndirectlyTo root raportsToSet
|> Set.toList
If you want to implement an efficient solution, you should interpret reportStructureSet as a graph in following way:
ints are vertices
pair of ints are directed edges
Then simply check which edges are reachable from "root" using a DFS.
I like f# puzzles, so I took a stab at this one. I hope that you enjoy.
let orgList = [(2, 1); (3, 2); (4, 2); (5, 3); (6, 4); (7, 3)]
let orgMap =
orgList
|> List.fold (fun acc item ->
let key = snd item
match Map.tryFind key acc with
| Some(value) ->
let map' = Map.remove key acc
Map.add(key) (item::value) map'
| None ->
Map.add(key) (item::[]) acc
) Map.empty<int, (int*int) list>
let findReports supervisor =
let rec findReports' acc collection =
match collection with
| head::tail ->
(findReports' (head::acc) tail)
# match Map.tryFind (fst head) orgMap with
| Some(value) -> (findReports' [] value)
| None -> []
| [] -> acc
findReports' [] (Map.find supervisor orgMap)
findReports 2
|> List.map fst
|> List.distinct
returns
val it : int list = [3; 4; 5; 7; 6]
findReports 2 returns
val it : (int * int) list = [(3, 2); (4, 2); (5, 3); (7, 3); (6, 4)]
I'll break it down to clarify.
let orgList = [ (1, 2); (1, 3); (1, 4); (2, 5); (3, 6); (4, 5); (5, 6); (5, 7) ]
We take your list of tuples and create a functional map of boss to ((report,boss) list). This might be known as an adjacency list, which is used for traversing graphs.
let orgMap =
orgList
|> List.fold (fun acc item ->
let key = snd item
match Map.tryFind key acc with
If there is a list of reports under a boss, add to that list.
| Some(reports) ->
let map' = Map.remove key acc
Map.add(key) (item::reports) map'
Otherwise, add to an empty list and insert into the dictionary.
| None ->
Map.add(key) (item::[]) acc
Start with an empty map as an accumulator.
) Map.empty<int, (int*int) list>
Recurse through the items to find all reports.
let findReports supervisor =
let rec findReports' acc collection =
match collection with
If there is an item, append it to the accumulator. This is BFS. If you switch the expression before and after the concatenate operator (#), it will become DFS.
| head::tail ->
(findReports' (head::acc) tail)
Concatenate the current list to the recursive list of reports to reports.
# match Map.tryFind (fst head) orgMap with
| Some(value) -> (findReports' [] value)
| None -> []
If at the end of the list, return the list.
| [] -> acc
Run the recursive function.
findReports' [] (Map.find supervisor orgMap)
Run the function.
findReports 7
Return only the reports
|> List.map fst
Don't report the report twice.
|> List.distinct
consider i have the following code,
let sqx= seq [1; 2; 3; 4;]
let sqy= seq [1; 2; 3; 4;]
let func sqx sqy = seq{
for x in sqx do
for y in sqy do yield x,y }
let cartesian sqx sqy= Seq.map (func sqx) sqy
cartesian sqx sqy
at the last line i am facing with the erorr:
The type int is not compatible with type seq<'a>
I have also tried to work with Seq.map2, but still the same problem.
If you look at the types involved, it may help you understand why the compiler complains.
The type of func is seq<'a> -> seq<'b> -> seq<'a * 'b>. That is, incidentally, also the type of Seq.zip; consider replacing func with Seq.zip.
The type of Seq.map is ('a -> 'b) -> seq<'a> -> seq<'b>.
If you look at cartesian, it simply it calls Seq.map with two arguments. The second argument is easiest to think about. From the type of Seq.map, we know that it must be seq<'something>.
That also means that func sqx must fit into the type 'a -> 'b, or, more specifically 'something -> 'b.
The type of func sqx, on the other hand, is seq<'b> -> seq<'a * 'b>, because it's partially applied. In other words, the input is seq<'b>.
This must fit into the 'something -> 'b argument passed to Seq.map, so 'something must be seq<'b>, and the return type is inferred to be seq<'a * 'b>. Thus, the overall type of cartesian is seq<'a> -> seq<#seq<'c>> -> seq<seq<'a * 'c>>.
The first argument to cartesian must be seq<'a>. That's OK, because sqx has the type seq<int>.
The next argument to cartesian must be seq<#seq<'c>>, but sqy has the type seq<int>. That's not the same type, and that's the reason cartesian sqx sqy doesn't compile.
My first guess is that you want something like seq [(1, 1); (1, 2); (1, 3); (1, 4); ...] (which would be the cartesian product of your sqx and sqy) and indeed you have this already implemented:
> func sqx sqy;;
val it : seq<int * int> = seq [(1, 1); (1, 2); (1, 3); (1, 4); ...]
but maybe you want to apply some function to all combinations of x in sqx and y in sqy? Then can modify your code a bit:
let allWith f sqx sqy =
seq{ for x in sqx do
for y in sqy do
yield f x y }
and have some fun:
> allWith (fun x y -> (x,y)) sqx sqy;;
val it : seq<int * int> = seq [(1, 1); (1, 2); (1, 3); (1, 4); ...]
> allWith (+) sqx sqy;;
val it : seq<int> = seq [2; 3; 4; 5; ...]
or maybe you want to write a function that takes the cartesian product of a sequence of sequences? This is more fun:
let rec cartesian (xss : 'a seq seq) =
if Seq.isEmpty xss then Seq.singleton Seq.empty else
let first = Seq.head xss
let rests = cartesian (Seq.tail xss)
seq { for x in first do
for xs in rests do
yield seq { yield x; yield! xs }
}
here is a simple example:
> cartesian [[1;2;3];[4];[5;6]] |> Seq.toArray;;
val it : seq<int> [] =
[|seq [1; 4; 5]; seq [1; 4; 6]; seq [2; 4; 5]; seq [2; 4; 6]; seq [3; 4; 5];
seq [3; 4; 6]|]
I'm trying to make a custom fold which goes through my sequence, and takes 2 Teams a time and assign them to a Match and then return a Match list in the end.
My current code is:
let myFold f s =
let rec myFold' f s acc =
match s with
| (a1::a2::a) -> f a1 a2::acc
| _ -> acc
myFold' f s []
Which gives me (int -> int) list
But obviously thats not going to work... What am I doing wrong?
-> I know that I just can create a recrusive function special made for this scenario, however I want to make it so abstract as possible for reuse.
Im' not quite sure that I get what you want to achieve. From sequence [1;2;3;4] you want to get [(1,2); (3,4)] or [(1,2); (2,3); (3,4)] ?
let fold f s =
let rec impl acc = function
| x::y::rest -> impl ((f x y)::acc) rest
| _ -> List.rev acc
impl [] s
let s = [1;2;3;4;5;6]
let r = fold (fun x y -> x,y) s // [(1, 2); (3, 4); (5, 6)]
let fold2 f s = Seq.pairwise s |> Seq.map f |> Seq.toList
let r2 = fold2 id s // [(1, 2); (2, 3); (3, 4); (4, 5); (5, 6)]