【问题标题】:Compare two List sorted比较两个排序的列表
【发布时间】:2015-07-19 14:43:09
【问题描述】:

我有这个编解码器,但它没有显示重复的元素,为什么?

cosinesim :: Ord a => [(a,Float)] -> [(a,Float)] -> [(a,Float,Float)]
cosinesim a b = go a b
    where
       go [] b = map (\l -> (fst l, 0, snd l)) b
       go a [] = map (\l -> (fst l, snd l, 0)) a
       go a@((x,n):t) b@((y,m):r) = case compare x y of
           LT -> (x,n,0) : go t b
           EQ -> (x,n,m) : go t r
           GT -> (y,0,m) : go a r

输入:两个列表排序。

List1=[(["variety"], 4.50),(["vegetable"], 3.50),(["velvet"], 2.50)]

List2=[(["variety"], 4.50),(["ve"], 3.50),(["velvet"], 2.50)]

输出:

[(["variety"], 4.50, 4.50 ), (["vegetable"], 3.50, 0), (["velvet"], 2.50 2.50) ,(["ve"], 0, 3.50)]

我的问题是因为只显示在两个列表中重复的元素,因为我想要的是所有元素都出现。

【问题讨论】:

  • 它应该做什么?
  • 我有两个列表。并将第一个列表与第二个进行比较。如果该项目存在于第二个列表中,则使我成为(项目 5.5)如果它仅存在于第一个列表中(元素 5.0)如果仅存在于第二个列表中(项目 0.5)。但只有它向我展示了重复的元素。
  • 什么是Item 5.5Element 5.0Item 0.5
  • is (string, Float, Float) 其中 String 取决于存在的列表。浮点数是在其他操作中计算的值。
  • 你能把它添加到你的问题中吗?格式在评论中被弄乱了,使用完整的markdown更容易阅读。

标签: list haskell merge compare


【解决方案1】:

由于您想组合两个列表的元素,因此我建议您使用来自Data.MapMap。然后,您可以使用unionunionWithunionWithKey 组合两张地图。不过,第二个在这里会更有用。由于您还希望仅使用0 来指示值来自第一个或第二个列表,因此最好有一个明确表示该值的数据类型:

import qualified Data.Map as M

data Those a b
    = This a        -- Only left
    | Those a b     -- Both
    | That b        -- Only right
    deriving (Eq, Show)

this :: a -> Those a b -> a
this def (This a)    = a
this def (Those a b) = a
this def _           = def

that :: b -> Those a b -> b
that def (That b)    = b
that def (Those a b) = b
that def _           = def

-- Give this a better name than Items
type Items k = M.Map k (Those Float Float)

这只是设置了我们稍后将使用的几个类型和工具。 Those 类型代表左、右或两者,thisthat 组合器帮助我们轻松地从中提取值,就像 Prelude 中的 maybe 组合器一样。

listToLeftItems :: Ord a => [(a, Float)] -> Items a
listToLeftItems = M.fromList . map (fmap This)

listToRightItems :: Ord a => [(a, Float)] -> Items a
listToRightItems = M.fromList . map (fmap That)

cosinesim :: Ord a => [(a, Float)] -> [(a, Float)] -> [(a, Float, Float)]
cosinesim left right
    = map (\(key, those) -> (key, this 0 those, that 0 those))
    $ M.toList
    $ M.unionWith go (listToLeftItems left)
                     (listToRightItems right)
    where
        go leftVal rightVal = case (leftVal, rightVal) of
            (This a, That b) -> Those a b
            (x, y) -> y  -- We know we won't have any other combinations,
                         -- this just keeps the compiler from throwing a warning

listToLeftItems 只是将This 应用于列表中的每个Float,然后将其转换为Map,同样适用于listToRightItems。现在您的函数只是将输入列表转换为Maps,使用go(我认为这很容易理解)将它们联合起来,转换回列表,然后将(a, Those Float Float) 展平为(a, Float, Float)。它为您提供所需的结果,但顺序不同。如果这很重要,您可以以此为基础按您想要的顺序获取它。

【讨论】:

    猜你喜欢
    • 2019-01-30
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    • 1970-01-01
    • 2011-06-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多