G-d willing
Hello,
How can I merge 2 lists into one list where the first element in the merged list will be of type data that has both first elements from the two lists?
For example, I have the following 2 lists:
nums = [1,2,3,4,5]
letters = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’]
I would like to have the result like so:
merged = [(1, ‘a’), (2, ‘b’), (3, ‘c’), (4, ‘d’), (5, ‘e’)]
I know how to do it using a recursive function, but I would like to know (and learn) if possible how to do it using the map
function
Use zip
(Module Prelude — Daml SDK 2.5.0 documentation):
import DA.Assert
import Daml.Script
testZip : Script ()
testZip =
let nums = [1,2,3,4,5]
letters = ["a", "b", "c", "d", "e"]
merged = zip nums letters
in merged === [(1, "a"), (2, "b"), (3, "c"), (4, "d"), (5, "e")]
1 Like
Thank you @dtanabe,
Basically in my situation, one of the lists is a bit more complex and not just a simple list of primitive type.
A similar situation is like the following:
data ComplexInt = ComplexInt
with
num : Int
name : Text
deriving (Eq, Show)
data MoreComplexInt = MoreComplexInt
with
complexInt : ComplexInt
num2 : Int
deriving (Eq, Show)
type FirstList = [ComplexInt]
type SecondList = [Int]
type ResultList = [MoreComplexInt]
I can write the following function:
funcMerge : FirstList -> SecondList -> ResultList
funcMerge [] [] = []
funcMerge [complexInt] [num2] = [MoreComplexInt with ..]
funcMerge (complexInt::restComplex) (num2::restNums) =
let
firstResult = MoreComplexInt with ..
restResults = funcMerge restComplex restNums
in firstResult :: restResults
funcMerge _ _ = []
Can it be done using map
?
It sounds like you should probably use zipWith
instead. But note that you can use zip
and map
regardless of whether the lists are primitive or complex. Given this sample data model and a sample function that “merges” a Person
and their shopping Cart
to create an Order
:
data Person = Person with
name : Text
address : Text
deriving (Eq, Show)
data Cart = Cart with
items : [Item]
deriving (Eq, Show)
data Item = Item with
productName : Text
quantity : Integer
deriving (Eq, Show)
data Order = Order with
name : Text
address : Text
items : [Item]
deriving (Eq, Show)
You can map
over the result from a zip
:
-- makeOrder takes a tuple as its argument
makeOrder : (Person, Cart) -> Order
makeOrder t = Order with
name = t._1.name
address = t._1.address
items = t._2.items
makeOrders : [Person] -> [Cart] -> [Order]
makeOrders people carts = map makeOrder $ zip people carts
But usually when you need to map
and zip
at the same time, you’re better off using zipWith
, which takes a function that takes two args, followed by two lists:
-- here makeOrder has two parameters instead of taking a tuple
makeOrder : Person -> Cart -> Order
makeOrder person cart = Order with
name = person.name
address = person.address
items = cart.items
-- then the implementation here is a bit simpler
makeOrders : [Person] -> [Cart] -> [Order]
makeOrders people carts = zipWith makeOrder people carts
-- you could also write `makeOrders` much more simply
makeOrders = zipWith makeOrder
1 Like
Thank you very much for the answer. It helped a lot.
1 Like