Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.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
Haskell 如果条件为true,则合并多个列表_Haskell - Fatal编程技术网

Haskell 如果条件为true,则合并多个列表

Haskell 如果条件为true,则合并多个列表,haskell,Haskell,我一直在想这件事,但似乎我缺乏哈斯克尔的经验无法让我度过难关。我在Stackoverflow上找不到类似的问题(大多数问题都与合并所有子列表有关,没有任何条件) 就这样。假设我有一个这样的列表: [[1, 2, 3], [3, 5, 6], [20, 21, 22]] 如果某种条件为真,是否有一种有效的方法来合并列表?假设我需要合并至少共享一个元素的列表。例如,结果将是: [[1, 2, 3, 3, 5, 6], [20, 21, 22]] 另一个示例(当可以合并所有列表时): 结果是: [

我一直在想这件事,但似乎我缺乏哈斯克尔的经验无法让我度过难关。我在Stackoverflow上找不到类似的问题(大多数问题都与合并所有子列表有关,没有任何条件)

就这样。假设我有一个这样的列表:

[[1, 2, 3], [3, 5, 6], [20, 21, 22]]
如果某种条件为真,是否有一种有效的方法来合并列表?假设我需要合并至少共享一个元素的列表。例如,结果将是:

[[1, 2, 3, 3, 5, 6], [20, 21, 22]]
另一个示例(当可以合并所有列表时):

结果是:

[[1, 2, 2, 3, 3, 4]]

谢谢你的帮助

关于效率,我不知道该说些什么,但我们可以分解正在发生的事情,至少可以得到几种不同的功能。特定的功能可能是可优化的,但明确需要什么是重要的

让我重新表述这个问题:对于一些集合X,一些二元关系R,和一些二元运算+,产生一个集合Q={X+y | X in X,y in X,xRy}。因此,对于您的示例,我们可能会让X表示一些列表集,R表示“xRy当且仅当X和y中至少有一个元素时”,并且+表示
++

简单的实现可能只是复制集合生成器符号本身

shareElement :: Eq a => [a] -> [a] -> Bool
shareElement xs ys = or [x == y | x <- xs, y <- ys]

v1 :: (a -> a -> Bool) -> (a -> a -> b) -> [a] -> [b]
v1 (?) (<>) xs = [x <> y | x <- xs, y <- xs, x ? y]
最明显的问题是我们得到了四个副本:两个副本来自于列表自身的合并,两个副本来自于列表“双向”的相互合并。出现此问题的原因是
List
Set
不同,因此无法杀死unique。当然,这是一个简单的解决方案,我们将在任何地方使用
Set

import Data.Set as Set

v2 :: (a -> a -> Bool) -> (a -> a -> b) -> Set.Set a -> Set.Set b
v2 (?) (<>) = Set.fromList . v1 (?) (<>) . Set.toList
这似乎有效。请注意,我们必须“遍历”
List
,因为
Set
由于其
Ord
约束而不能成为
Monad
Applicative
的实例

我还注意到,
Set
中有很多丢失的行为。例如,当我们的关系是对称的时,我们要么丢弃列表中的订单信息,要么必须同时处理
xy
yx

可以编写一些更方便的版本,如

v3 :: Monoid a => (a -> a -> Bool) -> [a] -> [a]
v3 r = v2 r mappend
如果我们假设该关系是一个等式关系,那么就可以建立更有效的关系,从那时起,我们可以在
O(n^2)
操作中进行
O(nd)
操作,其中
d
是该关系的分区(陪集)数


一般来说,这是一个非常有趣的问题。

我碰巧在这里写了一些类似的东西:

您可以修改它(尽管我不太确定效率):

输出:

*Main> objects example1
[[20,21,22],[3,5,6,1,2,3]]

*Main> objects example2
[[3,4,2,3,1,2]]

“可以合并任何两个列表,还是只合并连续的列表?”哈马尔忘了提到这一点。任意两个列表。一个猜测:这听起来像是实现了某种不相交的联合数据结构。列表并不是表示这一点的好方法。你能确切地告诉我们你想在这里实现什么吗?@NiklasB提供的例子和我想做的差不多——没有特别的用途。我一定要做一些关于不相交并的研究。因此,我想没有半途而废的方法来处理列表?如果你一定要处理列表,一般的方法是使用第一个列表,在每个列表中添加一个公共元素并重复,直到不再添加列表为止(因为你可以使用
[[1,2]、[3,4]、[1,4]]
,其中第一次通过不会拾取所有内容)。在未与第一个连接的子列表上递归。但我会寻找更好的数据结构。。。
Prelude Set> p $ Set.fromList $ map Set.fromList [[1,2], [2,1]]
fromList [fromList [1,2]]
v3 :: Monoid a => (a -> a -> Bool) -> [a] -> [a]
v3 r = v2 r mappend
import Data.List (delete, intersect) 

example1 = [[1, 2, 3], [3, 5, 6], [20, 21, 22]]
example2 = [[1, 2], [2, 3], [3, 4]]

objects zs = map concat . solve zs $ [] where
  areConnected x y = not . null . intersect x $ y
  solve []     result = result
  solve (x:xs) result =
    let result' = solve' xs [x]
    in solve (foldr delete xs result') (result':result) where
  solve' xs result =
    let ys = filter (\y -> any (areConnected y) result) xs
    in if null ys 
          then result
          else solve' (foldr delete xs ys) (ys ++ result)
*Main> objects example1
[[20,21,22],[3,5,6,1,2,3]]

*Main> objects example2
[[3,4,2,3,1,2]]