I am looking for a way to create a sequence consisting of every nth element of another sequence, but don't seem to find a way to do that in an elegant way. I can of course hack something, but I wonder if there is a library function that I'm not seeing.
The sequence functions whose names end in -i seem to be quite good for the purpose of figuring out when an element is the nth one or (multiple of n)th one, but I can only see iteri and mapi, none of which really lends itself to the task.
Example:
let someseq = [1;2;3;4;5;6]
let partial = Seq.magicfunction 3 someseq
Then partial should be [3;6]. Is there anything like it out there?
Edit:
If I am not quite as ambitious and allow for the n to be constant/known, then I've just found that the following should work:
let rec thirds lst =
match lst with
| _::_::x::t -> x::thirds t // corrected after Tomas' comment
| _ -> []
Would there be a way to write this shorter?
Seq.choose works nicely in these situations because it allows you do the filter work within the mapi lambda.
let everyNth n elements =
elements
|> Seq.mapi (fun i e -> if i % n = n - 1 then Some(e) else None)
|> Seq.choose id
Similar to here.
You can get the behavior by composing mapi with other functions:
let everyNth n seq =
seq |> Seq.mapi (fun i el -> el, i) // Add index to element
|> Seq.filter (fun (el, i) -> i % n = n - 1) // Take every nth element
|> Seq.map fst // Drop index from the result
The solution using options and choose as suggested by Annon would use only two functions, but the body of the first one would be slightly more complicated (but the principle is essentially the same).
A more efficient version using the IEnumerator object directly isn't too difficult to write:
let everyNth n (input:seq<_>) =
seq { use en = input.GetEnumerator()
// Call MoveNext at most 'n' times (or return false earlier)
let rec nextN n =
if n = 0 then true
else en.MoveNext() && (nextN (n - 1))
// While we can move n elements forward...
while nextN n do
// Retrun each nth element
yield en.Current }
EDIT: The snippet is also available here: http://fssnip.net/1R
Related
I have recently started learning f# and I have a problem with a task like the one in the subject line. I managed to solve this task but not using a recursive function. I have tried to convert my function to a recursive function but it does not work because in the function I create arrays which elements I then change. Please advise me how to convert my function to a recursive function or how else to perform this task.
let list = [8;4;3;3;5;9;-7]
let comp (a,b) = if a>b then a elif b = a then a else b
let maks (b: _ list) =
let x = b.Length
if x % 2 = 0 then
let tab = Array.create ((x/2)) 0
for i = 0 to (x/2)-1 do
tab.[i] <- (comp(b.Item(2*i),b.Item(2*i+1)))
let newlist = tab |> Array.toList
newlist
else
let tab = Array.create (((x-1)/2)+1) 0
tab.[(((x-1)/2))] <- b.Item(x-1)
for i = 0 to ((x-1)/2)-1 do
tab.[i] <- (comp(b.Item(2*i),b.Item(2*i+1)))
let newlist = tab |> Array.toList
newlist
It is worth noting that, if you were doing this not for learning purposes, there is a nice way of doing this using the chunkBySize function:
list
|> List.chunkBySize 2
|> List.map (fun l -> comp(l.[0], l.[l.Length-1]))
This splits the list into chunks of size at most 2. For each chunk, you can then compare the first element with the last element and that is the result you wanted.
If this is a homework question, I don't want to give away the answer, so consider this pseudocode solution instead:
If the list contains at least two elements:
Answer a new list consisting of:
The greater of the first two elements, followed by
Recursively applying the function to the rest of the list
Else the list contains less than two elements:
Answer the list unchanged
Hint: F#'s pattern matching ability makes this easy to implement.
Thanks to your guidance I managed to create the following function:
let rec maks2 (b: _ list,newlist: _ list,i:int) =
let x = b.Length
if x >= 2 then
if x % 2 = 0 then
if i < ((x/2)-1)+1 then
let d = (porownaj(b.Item(2*i),b.Item(2*i+1)))
let list2 = d::newlist
maks2(b,list2,i+1)
else
newlist
else
if i < ((x/2)-1)+1 then
let d = (porownaj(b.Item(2*i),b.Item(2*i+1)))
let list2 = d::newlist
maks2(b,list2,i+1)
else
let list3 = b.Item(x-1)::newlist
list3
else
b
The function works correctly, it takes as arguments list, empty list and index.
The only problem is that the returned list is reversed, i.e. values that should be at the end are at the beginning. How to add items to the end of the list?
You can use pattern matching to match and check/extract lists in one step.A typical recursive function, would look like:
let rec adjGreater xs =
match xs with
| [] -> []
| [x] -> [x]
| x::y::rest -> (if x >= y then x else y) :: adjGreater rest
It checks wether the list is empty, has one element, or has two elements and the remaining list in rest.
Then it builds a new list by either using x or y as the first element, and then compute the result of the remaing rest recursivly.
This is not tail-recursive. A tail-call optimized version would be, that instead of using the result of the recursive call. You would create a new list, and pass the computed valuke so far, to the recursive function. Usually this way, you want to create a inner recursive loop function.
As you only can add values to the top of a list, you then need to reverse the result of the recursive function like this:
let adjGreater xs =
let rec loop xs result =
match xs with
| [] -> result
| [x] -> x :: result
| x::y::rest -> loop rest ((if x >= y then x else y) :: result)
List.rev (loop xs [])
I'm reading a file and I want to do something with the first line, and something else with all the other lines
let lines = System.IO.File.ReadLines "filename.txt" |> Seq.map (fun r -> r.Trim())
let head = Seq.head lines
let tail = Seq.tail lines
```
Problem: the call to tail fails because the TextReader is closed.
What it means is that the Seq is evaluated twice: once to get the head once to get the tail.
How can I get the firstLine and the lastLines, while keeping a Seq and without reevaluating the Seq ?
the signature could be, for example :
let fn: ('a -> Seq<'a> -> b) -> Seq<'a> -> b
The easiest thing to do is probably just using Seq.cache to wrap your lines sequence:
let lines =
System.IO.File.ReadLines "filename.txt"
|> Seq.map (fun r -> r.Trim())
|> Seq.cache
Of note from the documentation:
This result sequence will have the same elements as the input sequence. The result can be enumerated multiple times. The input sequence is enumerated at most once and only as far as is necessary. Caching a sequence is typically useful when repeatedly evaluating items in the original sequence is computationally expensive or if iterating the sequence causes side-effects that the user does not want to be repeated multiple times.
I generally use a seq expression in which the Stream is scoped inside the expression. That will allow you to enumerate the sequence fully before the stream is disposed. I usually use a function like this:
let readLines file =
seq {
use stream = File.OpenText file
while not stream.EndOfStream do
yield stream.ReadLine().Trim()
}
Then you should be able to call Seq.head and get the first line in the fail, and Seq.last to get the last line in the file. I think this will technically create two different enumerators though. If you want to only read the file exactly one time, then materializing the sequence to a list or using a function like Seq.cache will be your best option.
I had an important use case for this, where I am using Seq.unfold to read a large number of blocks with REST reads, and sequentially processing each block, with further REST reads.
The reading of the sequence had to be both "lazy" but also cached to avoid duplicate re-evaluation (with every Seq.tail operation).
Hence finding this question and the accepted answer (Seq.cache). Thanks!
I experimented with Seq.cache and discovered that it worked as claimed (ie, lazy and avoid re-evaluation), but with one noteworthy condition - the first five elements of the sequence are always read first (and retained with 'cache'), so experiments on five or smaller numbers won't show lazy evaluation. However, after five, lazy evaluation kicks in for each element.
This code can be used to experiment. Try it for 5, and see no lazy evaluation, and then 10, and see each element after 5 being 'lazy' read, as required. Also remove Seq.cache to see the problem we are addressing (re-evaluation)
// Get a Sequence of numbers.
let getNums n = seq { for i in 1..n do printfn "Yield { %d }" i; yield i}
// Unfold a sequence of numbers
let unfoldNums (nums : int seq) =
nums
|> Seq.unfold
(fun (nums : int seq) ->
printfn "unfold: nums = { %A }" nums
if Seq.isEmpty nums then
printfn "Done"
None
else
let num = Seq.head nums // Value to yield
let tl = Seq.tail nums // Next State. CAUSES RE-EVALUTION!
printfn "Yield: < %d >, tl = { %A }" num tl
Some (num,tl))
// Get n numbers as a sequence, then unfold them as a sequence
// Observe that with 'Seq.cache' input is not re-evaluated unnecessarily,
// and also that lazy evaulation kicks in for n > 5
let experiment n =
getNums n
|> Seq.cache
// Without cache, Seq.tail causes the sequence to be re-evaluated
|> unfoldNums
|> Seq.iter (fun x -> printfn "Process: %d" x)
Is there a way to have a self-reference in F# sequence expression? For example:
[for i in 1..n do if _f(i)_not_in_this_list_ do yield f(i)]
which prevents inserting duplicate elements.
EDIT: In general case, I would like to know the contents of this_list before applying f(), which is very computationally expensive.
EDIT: I oversimplified in the example above. My specific case is a computationally expensive test T (T: int -> bool) having a property T(i) => T(n*i) so the code snippet is:
[for i in 1..n do if _i_not_in_this_list_ && T(i) then for j in i..i..n do yield j]
The goal is to reduce the number of T() applications and use concise notation. I accomplished the former by using a mutable helper array:
let mutable notYet = Array.create n true
[for i in 1..n do if notYet.[i] && T(i) then for j in i..i..n do yield j; notYet.[j] <- false]
You can have recursive sequence expression e.g.
let rec allFiles dir =
seq { yield! Directory.GetFiles dir
for d in Directory.GetDirectories dir do
yield! allFiles d }
but circular reference is not possible.
An alternative is to use Seq.distinct from Seq module:
seq { for i in 1..n -> f i }
|> Seq.distinct
or to convert sequence to set using Set.ofSeq before consumption as per #John's comment.
You may also decide to maintain information about the previously generated elements in an explicit way; for example:
let genSeq n =
let elems = System.Collections.Generic.HashSet()
seq {
for i in 1..n do
if not (elems.Contains(i)) then
elems.Add(i) |> ignore
yield i
}
There are several considerations here.
First, you can't check if f(i) is in a list or not before actually computing f(i). So I guess you meant that your check function is expensive, not f(i) itself. Correct me if I'm wrong.
Second, if check is indeed very computationally expensive, you may look for a more effective algorithm. There's no guarantee you will find one for every sequence, but they often exist. Then your code will be nothing but a single Seq.unfold.
Third. When there's no such optimization, you may take another approach. Within [for...yield], you only build a current element and you can't access prior ones. Instead of returning an element, building an entire list manually seems to be the way to go:
// a simple algorithm checking if some F(x) exists in a sequence somehow
let check (x:string) xs = Seq.forall (fun el -> not (x.Contains el)) xs
// a converter i -> something else
let f (i: int) = i.ToString()
let generate f xs =
let rec loop ys = function
| [] -> List.rev ys
| x::t ->
let y = f x
loop (if check y ys then y::ys else ys) t
loop [] xs
// usage
[0..3..1000] |> generate f |> List.iter (printf "%O ")
This F# seq expression looks tail-recursive to me, but I'm getting stack overflow exceptions (with tail-calls enabled). Does anybody know what I'm missing?
let buildSecondLevelExpressions expressions =
let initialState = vector expressions |> randomize
let rec allSeq state = seq {
for partial in state do
if count partial = 1
then yield Seq.head partial
if count partial > 1 || (count partial = 1 && depth (Seq.head partial) <= MAX_DEPTH) then
let allUns = partial
|> pick false 1
|> Seq.collect (fun (el, rr) -> (createExpUnaries el |> Seq.map (fun bn -> add rr bn)))
let allBins = partial // Careful: this case alone produces result recursivley only if |numbers| is even (rightly!).
|> pick false 2
|> Seq.collect (fun (el, rr) -> (createExpBinaries el |> Seq.map (fun bn -> add rr bn)))
yield! allSeq (interleave allBins allUns)
}
allSeq initialState
If you're wondering, though it shouldn't be important, pick is used to generate combinations of elements in a sequence and interleave interleaves elements from 2 sequences. vector is a constructor for a ResizeArray.
As Gideon pointed out, this is not tail-recursive, because you still have other elements in the 'state' list to process. Making this tail-recursive isn't straightforward, because you need some queue of elements that should be processed.
The following pseudo-code shows one possible solution. I added work parameter that stores the remaining work to be done. At every call, we process just the first element. All other elements are added to the queue. When we finish, we pick more work from the queue:
let rec allSeq state work = seq {
match state with
| partial::rest ->
// Yield single thing to the result - this is fine
if count partial = 1 then yield Seq.head partial
// Check if we need to make more recursive calls...
if count partial > 1 || (* ... *) then
let allUns, allBins = // ...
// Tail-recursive call to process the current state. We add 'rest' to
// the collected work to be done after the current state is processed
yield! allSeq (interleave allBins allUns) (rest :: work)
else
// No more processing for current state - let's take remaining
// work from the 'work' list and run it (tail-recursively)
match work with
| state::rest -> yield! allSeq state rest
| [] -> () //completed
| _ ->
// This is the same thing as in the 'else' clause above.
// You could use clever pattern matching to handle both cases at once
match work with
| state::rest -> yield! allSeq state rest
| [] -> () } //completed
I cannot find a definition of which calls inside a sequence expression are in tail position in F# so I would strongly recommend not writing code that depends upon the semantics of the current implementation, i.e. this is undefined behaviour.
For example, trying to enumerate (e.g. applying Seq.length) the following sequence causes a stack overflow:
let rec xs() = seq { yield! xs() }
but, as Tomas pointed out, the following does actually work:
let rec xs n = seq { yield n; yield! xs(n+1) }
My advice is to always replace recursive sequence expressions with Seq.unfold instead. In this case, you probably want to accumulate the work to be done (e.g. when you recurse into a left branch you push the right branch onto the stack in the accumulator).
FWIW, even the F# language reference gets this wrong. It gives the following code for flattening a tree:
type Tree<'a> =
| Tree of 'a * Tree<'a> * Tree<'a>
| Leaf of 'a
let rec inorder tree =
seq {
match tree with
| Tree(x, left, right) ->
yield! inorder left
yield x
yield! inorder right
| Leaf x -> yield x
}
Their own code kills F# interactive with a stack overflow when fed a deep tree on the left.
This is not going to be tail recursive because you could be calling recursively multiple times. To translate to a pseudo-code:
allSeq(state)
{
foreach (partial in state)
{
if (...)
{
yield ...
}
if (...)
{
...
//this could be reached multiple times
yield! allSeq(...)
}
}
}
I've trying to learn F#. I'm a complete beginner, so this might be a walkover for you guys :)
I have the following function:
let removeEven l =
let n = List.length l;
let list_ = [];
let seq_ = seq { for x in 1..n do if x % 2 <> 0 then yield List.nth l (x-1)}
for x in seq_ do
let list_ = list_ # [x];
list_;
It takes a list, and return a new list containing all the numbers, which is placed at an odd index in the original list, so removeEven [x1;x2;x3] = [x1;x3]
However, I get my already favourite error-message: Incomplete construct at or before this point in expression...
If I add a print to the end of the line, instead of list_:
...
print_any list_;
the problem is fixed. But I do not want to print the list, I want to return it!
What causes this? Why can't I return my list?
To answer your question first, the compiler complains because there is a problem inside the for loop. In F#, let serves to declare values (that are immutable and cannot be changed later in the program). It isn't a statement as in C# - let can be only used as part of another expression. For example:
let n = 10
n + n
Actually means that you want the n symbol to refer to the value 10 in the expression n + n. The problem with your code is that you're using let without any expression (probably because you want to use mutable variables):
for x in seq_ do
let list_ = list_ # [x] // This isn't assignment!
list_
The problematic line is an incomplete expression - using let in this way isn't allowed, because it doesn't contain any expression (the list_ value will not be accessed from any code). You can use mutable variable to correct your code:
let mutable list_ = [] // declared as 'mutable'
let seq_ = seq { for x in 1..n do if x % 2 <> 0 then yield List.nth l (x-1)}
for x in seq_ do
list_ <- list_ # [x] // assignment using '<-'
Now, this should work, but it isn't really functional, because you're using imperative mutation. Moreover, appending elements using # is really inefficient thing to do in functional languages. So, if you want to make your code functional, you'll probably need to use different approach. Both of the other answers show a great approach, although I prefer the example by Joel, because indexing into a list (in the solution by Chaos) also isn't very functional (there is no pointer arithmetic, so it will be also slower).
Probably the most classical functional solution would be to use the List.fold function, which aggregates all elements of the list into a single result, walking from the left to the right:
[1;2;3;4;5]
|> List.fold (fun (flag, res) el ->
if flag then (not flag, el::res) else (not flag, res)) (true, [])
|> snd |> List.rev
Here, the state used during the aggregation is a Boolean flag specifying whether to include the next element (during each step, we flip the flag by returning not flag). The second element is the list aggregated so far (we add element by el::res only when the flag is set. After fold returns, we use snd to get the second element of the tuple (the aggregated list) and reverse it using List.rev, because it was collected in the reversed order (this is more efficient than appending to the end using res#[el]).
Edit: If I understand your requirements correctly, here's a version of your function done functional rather than imperative style, that removes elements with odd indexes.
let removeEven list =
list
|> Seq.mapi (fun i x -> (i, x))
|> Seq.filter (fun (i, x) -> i % 2 = 0)
|> Seq.map snd
|> List.ofSeq
> removeEven ['a'; 'b'; 'c'; 'd'];;
val it : char list = ['a'; 'c']
I think this is what you are looking for.
let removeEven list =
let maxIndex = (List.length list) - 1;
seq { for i in 0..2..maxIndex -> list.[i] }
|> Seq.toList
Tests
val removeEven : 'a list -> 'a list
> removeEven [1;2;3;4;5;6];;
val it : int list = [1; 3; 5]
> removeEven [1;2;3;4;5];;
val it : int list = [1; 3; 5]
> removeEven [1;2;3;4];;
val it : int list = [1; 3]
> removeEven [1;2;3];;
val it : int list = [1; 3]
> removeEven [1;2];;
val it : int list = [1]
> removeEven [1];;
val it : int list = [1]
You can try a pattern-matching approach. I haven't used F# in a while and I can't test things right now, but it would be something like this:
let rec curse sofar ls =
match ls with
| even :: odd :: tl -> curse (even :: sofar) tl
| even :: [] -> curse (even :: sofar) []
| [] -> List.rev sofar
curse [] [ 1; 2; 3; 4; 5 ]
This recursively picks off the even elements. I think. I would probably use Joel Mueller's approach though. I don't remember if there is an index-based filter function, but that would probably be the ideal to use, or to make if it doesn't exist in the libraries.
But in general lists aren't really meant as index-type things. That's what arrays are for. If you consider what kind of algorithm would require a list having its even elements removed, maybe it's possible that in the steps prior to this requirement, the elements can be paired up in tuples, like this:
[ (1,2); (3,4) ]
That would make it trivial to get the even-"indexed" elements out:
thelist |> List.map fst // take first element from each tuple
There's a variety of options if the input list isn't guaranteed to have an even number of elements.
Yet another alternative, which (by my reckoning) is slightly slower than Joel's, but it's shorter :)
let removeEven list =
list
|> Seq.mapi (fun i x -> (i, x))
|> Seq.choose (fun (i,x) -> if i % 2 = 0 then Some(x) else None)
|> List.ofSeq