Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# combining two sequences

I have two sequences that I would like to combine somehow as I need the result of the second one printed right next to the first. The code is currently where playerItems refers to a list:

seq state.player.playerItems
      |> Seq.map (fun i -> i.name)
      |> Seq.iter (printfn "You have a %s")

seq state.player.playerItems
      |> Seq.map (fun i -> i.description) |> Seq.iter (printfn "Description =  %s")

The result currently is

You have a Keycard
You have a Hammer
You have a Wrench
You have a Screw
Description =  Swipe to enter
Description =  Thump
Description =  Grab, Twist, Let go, Repeat
Description =  Twisty poke

However, I need it to be

You have a Keycard
Description =  Swipe to enter
You have a Hammer
Description =  Thump

Any help with this would be very appreciated.

like image 728
Kieran Dee Avatar asked Jan 02 '23 23:01

Kieran Dee


1 Answers

As Foggy Finder said in the comments, in your specific case you really don't have two sequences, you have one sequence and you want to print two lines for each item, which can be done with a single Seq.iter like this:

state.player.playerItems  // The "seq" beforehand is not necessary
|> Seq.iter (fun player -> printfn "You have a %s\nDescription = %s" player.name player.description)

However, I'll also tell you about two ways to combine two sequences, for the time when you really do have two different sequences. First, if you want to turn the two sequences into a sequence of tuples, you'd use Seq.zip:

let colors = Seq.ofList ["red"; "green"; "blue"]
let numbers = Seq.ofList [25; 73; 42]
let pairs = Seq.zip colors numbers
printfn "%A" pairs
// Prints: seq [("red", 25); ("green", 73); ("blue", 42)]

If you want to combine the two sequences in some other way than producing tuples, use Seq.map2 and pass it a two-parameter function:

let colors = Seq.ofList ["red"; "green"; "blue"]
let numbers = Seq.ofList [25; 73; 42]
let combined = Seq.map2 (fun clr num -> sprintf "%s: %d" clr num) colors numbers
printfn "%A" combined
// Prints: seq ["red: 25"; "green: 73"; "blue: 42"]

Finally, if all you want is to perform some side-effect for each pair of items in the two sequences, then Seq.iter2 is your friend:

let colors = Seq.ofList ["red"; "green"; "blue"]
let numbers = Seq.ofList [25; 73; 42]
Seq.iter2 (fun clr num -> printfn "%s: %d" clr num)

That would print the following three lines to the console:

red: 25
green: 73
blue: 42

Note how in the Seq.iter function, I'm not storing the result. That's because the result of Seq.iter is always (), the "unit" value that is F#'s equivalent of void. (Except that it's much more useful than void, for reasons that are beyond the scope of this answer. Search Stack Overflow for "[F#] unit" and you should find some interesting questions and answers, like this one.

like image 70
rmunn Avatar answered Jan 11 '23 11:01

rmunn