首页 > 解决方案 > 如果它们不相同,则从两个列表中取一个元素/从一个列表中取特定的 2 个元素

问题描述

我有两个包含此数据类型的列表:

data Student = Student {firstName::String, lastName::String, age::Int}
   deriving (Show, Read, Eq)

我需要制作另一个列表,其中包含这两个列表中的唯一元素。理想情况下,此列表将仅包含 firstNames,因为它们只能在这个字段 firstName 中有所不同。

我有点解决了,我的解决方案是这样的:

listOfChanges :: [Student] -> [Student] -> [String]
listOfChanges list1 list2 =
                let c = intersect list1 list2
                    b = union list1 list2
                in  listEvent(nSame b c)

nSame (x:xs) ys = if x `elem` ys
                 then nSame xs ys
                 else x:nSame xs (delete x ys)
nSame [] _ = []
nSame _ [] = []

extractName::Student -> String
extractName (Student firstName _ _) = firstName

listEvent :: [Student] -> [String]
listEvent list = map extractName list

但我想将最终列表转换为类型列表:

data StudentsFirstNameChangeEvent = StudentsFirstNameChangeEvent {oldName::String, newNames::String}
  deriving (Show, Read, Eq)

我的最终清单:

["Alicja","Batrek","Damian","AlicjaX","BatrekX","DamianX"]

“Alicja”,“Batrek”,“Damian” - oldNames。“AlicjaX”、“BatrekX”、“DamianX” - 新名称。

当它实际上应该是:

[StudentsFirstNameChangeEvent {oldName = "Alicja", newName = "Alicjax"},StudentsFirstNameChangeEvent {oldName = "Bartek", newName = "Bartekx"}, ...]
enter code here

我认为我已经完成了 haskell,但这是我的最终进展:

correctSplit :: [String] -> [[String]]
correctSplit list = 
              let x = length list
                  x1 = (x `div` 2)
              in splitEvery x1 list

splitEvery _ [] = []
splitEvery n list = first : (splitEvery n rest)
  where
    (first,rest) = splitAt n list

proList :: [Student] -> [Student] -> [String]
proList list1 list2 =
              let x = listOfChanges list1 list2
                  x2 = correctSplit x
                  x3 = x2 !! 0
                  x4 = x2 !! 1
              in merge x3 x4


merge :: [a] -> [a] -> [a]
merge xs     []     = xs
merge []     ys     = ys
merge (x:xs) (y:ys) = x : y : merge xs ys

最终名单现在是:

["Alicja","AlicjaX","Batrek","BatrekX","Damian","DamianX"]

但我仍然不知道如何将这些列表中的任何一个转换为我需要的类型。

好吧,事实证明处理这个的正确方法要短得多:

listOfChanges :: [Student] -> [Student] -> [StudentsFirstNameChangeEvent]
listOfChanges list1 list2 =
                    let mask = intersect list1 list2
                        x1 = list1 \\ mask
                        x2 = list2 \\ mask
                    in changeList x1 x2


changeList :: [Student] -> [Student] -> [StudentsFirstNameChangeEvent]
changeList a b = zipWith StudentsFirstNameChangeEvent (map                   firstName a) (map firstName b)

标签: listhaskell

解决方案


推荐阅读