简体   繁体   English

从给定谓词的列表中配对元素

[英]Pairing up elements from a list given a predicate

I'm relatively new to Haskell and found a challenge to create a set of tuples which greedily takes from a list given a predicate.我对 Haskell 比较陌生,发现创建一组元组的挑战,这些元组贪婪地从给定谓词的列表中获取。 For example, using (\\x -> \\y -> odd(x+y)) on [2,3,4,5,6,7] could return [(2,3),(3,2),(4,5),(5,4),(6,7),(7,6)] or [(2,7),(6,5),(3,4),(4,3),(5,6),(7,2)] or any other valid set of pairings, as long as it's one where each pair is symmetrical, and all items from the set are included in one and only one pairing.例如,在[2,3,4,5,6,7]上使用(\\x -> \\y -> odd(x+y))可以返回[(2,3),(3,2),(4,5),(5,4),(6,7),(7,6)][(2,7),(6,5),(3,4),(4,3),(5,6),(7,2)]或任何其他有效的配对组,只要它是每对对称的一组,并且该组中的所有项目都包含在一个且仅一个配对中。 A key part of my challenge is to learn to work with monads, specifically Maybe/Just/Nothing, so my current function is Eq a => (a -> a -> Bool) -> [a] -> Maybe [(a,a)] where Nothing is returned if a list of tuples including every element cannot be made;我挑战的一个关键部分是学习使用 monad,特别是 Maybe/Just/Nothing,所以我当前的函数是Eq a => (a -> a -> Bool) -> [a] -> Maybe [(a,a)] ,其中Nothing如果不能作出元组包括每个元素的列表被返回; for example running (\\x -> \\y -> even(x+y)) on [2,3,4,5,6,7] would return Nothing , as you can't pair up all the elements to fit that predicate without leaving some out.例如,在[2,3,4,5,6,7]上运行(\\x -> \\y -> even(x+y))将返回Nothing ,因为您无法配对所有元素以适应它谓词而不遗漏一些。

To start off, I thought I could generate a full list of possible pairs and filter them with the predicate.首先,我想我可以生成一个完整的可能对列表并用谓词过滤它们。 My function at present is test p xs = filter (uncurry p) [(x,y) | (x:ys) <- tails xs, y <- ys]我目前的功能是test p xs = filter (uncurry p) [(x,y) | (x:ys) <- tails xs, y <- ys] test p xs = filter (uncurry p) [(x,y) | (x:ys) <- tails xs, y <- ys] , with the idea that later on I can remove tuples with duplicate first values (perhaps somehow using nubBy ?), run swap from Data.Tuple on what's left in my list to make my pairs symmetrical, and then run a final check to see if all the elements from the list have been included so I know whether to return nothing. test p xs = filter (uncurry p) [(x,y) | (x:ys) <- tails xs, y <- ys]的想法,以后我可以删除重复的第一值的元组(可能以某种方式使用nubBy ?),运行swapData.Tuple在什么在我的左边列表使我的对对称,然后运行最终检查以查看列表中的所有元素是否已包含在内,以便我知道是否不返回任何内容。 I realise, however, that there's probably a better way of going about this that performs fewer redundant actions and does the final check for returning Nothing earlier on.然而,我意识到可能有更好的方法来解决这个问题,即执行更少的冗余操作,并在更早的时候对返回 Nothing 进行最终检查。 I've tried to play around with list comprehension, but I can't come up with anything serviceable.我试图玩弄列表理解,但我想不出任何有用的东西。

A tuple (x, y) is inherently ordered: (x, y) != (y, x) .元组(x, y)具有固有的顺序: (x, y) != (y, x) It would be helpful to define an "unordered" pair type for filtering:为过滤定义“无序”对类型会很有帮助:

newtype Pair x = Pair { unpair :: (x, x) }

instance Eq a => Eq (Pair a) where
  (Pair p1) == (Pair p2) = p1 == p2 || p1 == swap p2

Then you can use a simpler method of generating sample pairs, using the Applicative instance for lists.然后您可以使用更简单的方法来生成样本对,使用列表的Applicative实例。 You can filter out duplicates later, using Pair .您可以稍后使用Pair过滤掉重复项。

>>> (,) <$> [1, 2, 3] <*> [1, 2, 3]
[(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]

Once you have filtered the above list, use nub by first converting all your initial results to Pair values, deduplicate using nub , then convert back to tuples:过滤完上述列表后,使用nub首先将所有初始结果转换为Pair值,使用nub重复数据删除,然后转换回元组:

result :: Eq x => [(x,x)] -> [(x,x)]
result = map unpair . nub . map Pair

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 计算列表中满足给定谓词的元素数 - Counting number of elements in a list that satisfy the given predicate Haskell 配对元素列表 - Haskell pairing elements of a single list 给定一个列表,如何仅对每两个元素满足二元谓词的子列表执行某些转换? - Given a list, how can I perform some transformation only on sub-lists whose each two elements satisfy a binary predicate? 从另一个列表中给定索引的列表元素中提取 - Extract from a list elements with indexes given in another list 在 Haskell 中,创建一个包含子列表的列表,其中包含给定列表中的重复元素 - In Haskell, create a list with sublists with repeating elements from a given list 我们可以构造一个满足给定位谓词的无限列表吗? - Can we construct an infinite list that satisfies a given bit predicate? Haskell:根据列表中所有其他元素的谓词过滤列表 - Haskell: Filtering a list based on a predicate for all other elements in the list 如果谓词成立,则从列表中删除项目 - Removing items from a list if a predicate holds Haskell列表:根据元素在列表中的位置替换元素 - Haskell list: Replacing elements given their locations in the list Haskell:给定一个数字列表和一个数字 k,返回列表中的任意两个数字加起来是否为 k - Haskell: Given a list of numbers and a number k, return whether any two numbers from the list add up to k
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM