Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
618 views
in Technique[技术] by (71.8m points)

collections - Take while running total smaller than value

I am trying to generate a list of even integers while the sum of the items in the list is less equal a given number. For instance if the threshold k is 20, then the expected output is [0;2;4;6;8]

I can generate a list where the largest value is smaller by the threshold like this:

let listOfEvenNumbersSmallerThanTwenty =
    Seq.unfold (fun x -> Some(x, x + 1)) 0 // natural numbers
    |> Seq.filter (fun x -> x % 2 = 0) // even numbers
    |> Seq.takeWhile (fun x -> x <= 20)
    |> List.ofSeq

(I know that I can combine the unfold and filter to Some(x, x + 2) but this task is for educational purposes)

I managed to create a different list with a running total smaller than the threshold:

let runningTotal =
    listOfEvenNumbersSmallerThanTwenty 
    |> Seq.scan (+) 0
    |> Seq.filter (fun x -> x < 20)
    |> List.ofSeq

But in order to do that, I have set the threshold in listOfEvenNumbersSmallerThanTwenty (which is way more than the items needed) and I have lost the initial sequence. I did also try to find that using a mutable value but didn't really like that route.

question from:https://stackoverflow.com/questions/65850132/take-while-running-total-smaller-than-value

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Best stick to lazy evaluation if you don't know the number of elements beforehand.

let seqOfEvenNumbers =
    Seq.unfold (fun x -> Some(x, x + 1)) 0 // natural numbers
    |> Seq.filter (fun x -> x % 2 = 0) // even numbers

Note we didn't use Seq.toList.

Now for a functional flow processing the elements in one go.

let listOfEvenNumbersForRunningTotalUpTo threshold =
    seqOfEvenNumbers
    |> Seq.scan (fun (total, _) x -> (total + x, x)) (0, 0)
    |> Seq.skip 1
    |> Seq.takeWhile (fun acc -> fst acc <= threshold)
    |> Seq.map snd
    |> Seq.toList

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...