Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 从元组列表中删除反向重复项_List_Haskell_Functional Programming - Fatal编程技术网

List 从元组列表中删除反向重复项

List 从元组列表中删除反向重复项,list,haskell,functional-programming,List,Haskell,Functional Programming,所以基本上我有一个元组列表[(a,b)],我必须从中进行一些过滤。一项工作是删除反向重复项,这样,如果列表中存在(a,b)和(b,a),我就只取其中一个实例。但对清单的理解并没有太大帮助。如何有效地进行这项工作 谢谢您可以使用自己的功能过滤它们: checkEqTuple :: (a, b) -> (a, b) -> Bool checkEqTuple (x, y) (x', y') | (x==y' && y == x') = True

所以基本上我有一个元组列表[(a,b)],我必须从中进行一些过滤。一项工作是删除反向重复项,这样,如果列表中存在(a,b)和(b,a),我就只取其中一个实例。但对清单的理解并没有太大帮助。如何有效地进行这项工作


谢谢

您可以使用自己的功能过滤它们:

checkEqTuple :: (a, b) -> (a, b) -> Bool
checkEqTuple (x, y) (x', y') | (x==y' && y == x') = True
                             | (x==x' && y == y') = True
                             | otherwise          = False
然后使用


也许一种有效的方法(O(n log(n)))是跟踪已经添加的元组(及其反向),使用:

函数
removeDups
调用带有列表和空集的辅助函数
removeDups'
。对于每一对,如果它或它的逆项在集合中,则传递它;否则,它和它的倒数都被加上,并且尾部被处理\

复杂度为O(n log(n)),因为集合的大小在每一步的n中最多是线性的


示例

...

main = do
    putStrLn $ show $ removeDups [(1, 2), (1, 3), (2, 1)]


我觉得我在重复我自己,但没关系。这些代码都没有经过测试甚至编译,因此可能存在bug。假设我们可以对效率施加
Ord
约束。我将从成对集合的有限实现开始

import qualified Data.Set as S
import qualified Data.Map.Strict as M

newtype PairSet a b =
  PS (M.Map a (S.Set b))

empty :: PairSet a b
empty = PS M.empty

insert :: (Ord a, Ord b)
       => (a, b) -> PairSet a b -> PairSet a b
insert (a, b) (PS m) = PS $ M.insertWith S.union a (S.singleton b) m

member :: (Ord a, Ord b)
       => (a, b) -> PairSet a b -> Bool
member (a, b) (PS m) =
  case M.lookup a m of
    Nothing -> False
    Just s -> S.member b s
现在我们只需要跟踪我们看到的配对

order :: Ord a => (a, a) -> (a, a)
order p@(a, b)
  | a <= b = p
  | otherwise = (b, a)

nubSwaps :: Ord a => [(a,a)] -> [(a,a)]
nubSwaps xs = foldr go (`seq` []) xs empty where
  go p r s
    | member op s = r s
    | otherwise = p : r (insert op s)
    where op = order p
顺序:Ord a=>(a,a)->(a,a) 订单p@(a,b) |a[(a,a)]->[(a,a)] nubSwaps xs=foldr go(`seq`[])xs空,其中 加油 |成员op s=r s |否则=p:r(插入op s) 式中,op=订单p
如果a和b是有序且可比较的,您可以这样做:

[(a,b) | (a,b) <- yourList, a<=b]

[(a,b)|(a,b)我认为它应该是块状的,而不是块状的。很好的解决方案!它是O(n^2)。你不必检查(b,a)如果您已经将这两个变量都设置到集合中,则为成员身份。@Hynek Pichi Vychodil这是真的。谢谢!更正。这也可以表示为折叠。例如,如果顺序很重要,则类似于
snd.foldr(\pair@(a,b)acc@(seen,result)->如果pair`set.member`seen|(b,a)`set.member`seen`seen,则为acc else(已看到Set.insert对,对:结果))mempty
,或者一个带有
foldl'
的版本,如果过滤应该朝另一个方向进行。那么使用此解决方案,问题是插入中的解算器,对吗?@JonPurdy这是一个很好的观点-总是需要考虑某个东西是否是
折叠的
。谢谢。对于您的特定应用程序,在仅y列表中有一个变量?(例如,如果列表只包含
[(2,1)]
,您是否可以将列表“简化”为
[(1,2)]
?下面给出的大多数答案都假设您需要保留没有反向重复的对,但如果您不这样做,解决方案可能会更简单。
import qualified Data.Set as S
import qualified Data.Map.Strict as M

newtype PairSet a b =
  PS (M.Map a (S.Set b))

empty :: PairSet a b
empty = PS M.empty

insert :: (Ord a, Ord b)
       => (a, b) -> PairSet a b -> PairSet a b
insert (a, b) (PS m) = PS $ M.insertWith S.union a (S.singleton b) m

member :: (Ord a, Ord b)
       => (a, b) -> PairSet a b -> Bool
member (a, b) (PS m) =
  case M.lookup a m of
    Nothing -> False
    Just s -> S.member b s
order :: Ord a => (a, a) -> (a, a)
order p@(a, b)
  | a <= b = p
  | otherwise = (b, a)

nubSwaps :: Ord a => [(a,a)] -> [(a,a)]
nubSwaps xs = foldr go (`seq` []) xs empty where
  go p r s
    | member op s = r s
    | otherwise = p : r (insert op s)
    where op = order p
[(a,b) | (a,b) <- yourList, a<=b]