haskell - 如何根据第一个值生成元组列表的笛卡尔连接?
问题描述
我有一个类型的元组列表,(Int,String)
我想生成一个类型列表,[String]
其中每个字符串都是具有相同Int
值的元组的第二个元素的笛卡尔连接排列。例如:
输入:[(1,"abc"),(1,"def"),(2,"ghi"),(2,"kl")]
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf", "gk", "gl", "hk", "hl", "ik", "il"]
我试过这个,但我找不到一种方法来排列具有相同Int
值的元组:
possible_keys :: [(Int,String)] -> [String]
possible_keys subkeys = [ key | keysize <- keysizes, key<-keys]
where keysizes = map (fst) subkeys
keys = sequence (map (snd) subkeys)
有什么提示吗?
解决方案
您可以使用groupBy
将元组组分开:
import Data.Function (on)
import Data.Ord (comparing)
import Data.List
possible_keys :: Ord k => [(k, [c])] -> [[c]]
possible_keys = concat . fmap sequenceA . fmap (fmap snd)
. groupBy ((==) `on` fst) . sortBy (comparing fst)
(我假设输入列表不一定是排序的。我只按键排序以使其侵入性最小。comparing fst
与 相同;不幸的是,标准库中还compare `on` fst
没有类似的。与,只是更一般。)equating
sequenceA
sequence
这可以瘦一点。第二函子定律允许我们结合 的连续使用fmap
:
possible_keys :: Ord k => [(k, [c])] -> [[c]]
possible_keys = concat . fmap (sequenceA . fmap snd)
. groupBy ((==) `on` fst) . sortBy (comparing fst)
fmap
其次sequenceA
是traverse
:
possible_keys :: Ord k => [(k, [c])] -> [[c]]
possible_keys = concat . fmap (traverse snd)
. groupBy ((==) `on` fst) . sortBy (comparing fst)
最后,在一个列表fmap
后面是(或,但这在这里有点太神秘了):concat
concatMap
(=<<)
possible_keys :: Ord k => [(k, [c])] -> [[c]]
possible_keys = concatMap (traverse snd)
. groupBy ((==) `on` fst) . sortBy (comparing fst)
请注意,这将为只有一个元组的键生成长度为 1 的字符串 - sequenceA ["abc"]
is ["a","b","c"]
。如果你不想这样,你可以filter
在之后立即groupBy
删除那些只有一个元组的元组组。
推荐阅读
- r - 从R中的两个向量制作表格
- php - 调试 cURL - 如何查看请求的正文?
- javascript - 反应:异步和等待不与 fetch 一起工作
- ms-access - 搜索列表到过滤形式 ms-access
- reactjs - 将图像上传到 Amazon AWS S3,然后发送到使用 React Native 开发的移动应用程序
- flutter - 在 null 上调用了方法“addSystemCategories”。在颤振中
- java - 在android java处理上读取文件夹目录内容
- java - 在 Spring Boot 中将 XML 解析为 JSON
- python - 有什么方法可以用 Python 函数属性中的值替换变量?
- typescript - ValidationPipes 不适用于 Body 特定类型