3

所以基本上,如果我有一个(有限或无限)字符串列表(有限或无限)列表,是否可以先按长度排序列表,然后按字典顺序排序,不包括重复项?示例输入/输出将是:

输入:

[["a", "b",...], ["a", "aa", "aaa"], ["b", "bb", "bbb",...], ... ]

输出:

[“a”,“b”,“aa”,“bb”,“aaa”,“bbb”,...]

我知道输入列表不是有效的 haskell 表达式,但假设有这样的输入。我尝试使用合并算法,但它往往会挂在我给它的输入上。有人可以解释并展示一个可以做到这一点的不错的排序功能吗?如果没有这样的功能,你能解释一下为什么吗?

如果有人不明白我所说的排序顺序是什么意思,我的意思是最短长度的字符串首先排序,如果一个或多个字符串长度相同,则使用 < 运算符对它们进行排序。

谢谢!

4

6 回答 6

15

最终,您无法对无限列表进行排序,因为列表尾部的项目可能会一直渗透到结果的前面,因此在看到最后一项之前,您无法完成对无限列表的排序,但你的名单是无限的,所以你永远不会到达那里。

您甚至可以尝试对无限列表进行排序的唯一方法是需要对列表的居民进行限制。如果列表项的值来自一个有根据的集合并且列表的内容是唯一的,那么您至少可以在返回列表初始元素的元素方面取得一些进展。例如,如果列表是不同的自然数,您可以返回您看到的第一个 0,然后是第一个 1,等等。但是在看到 2 之前,您无法在结果中取得任何进展,无论列表有多远你去了。最终,如果您曾经跳过集合中的一个元素,因为它不存在于源中,您将停止生成新的输出元素,直到您掌握了整个输入。

你可以对字符串做同样的事情,因为它们是有根据的,但如果你计划返回所有可能的字符串,那甚至是遥不可及的。

简而言之,如果你需要这个,你就会以错误的方式解决你遇到的问题。这不是您想要使用的任何解决方案的易处理路径。

正如 yairchu 所指出的,合并有限数量的已排序无限列表可以正常工作。

于 2010-03-07T07:25:10.770 回答
9
  • 一般来说,对无限列表进行排序是不可能的。因为最小的项目可能在无限的位置,我们必须在输出之前找到它。

  • 合并无限排序列表是可能的。

  • 一般来说,合并一个无限的排序列表是不可能的。出于与对它们进行排序相同的原因。

  • 可以合并一个无限的已排序列表,这些列表按头排序(forall i j. i < j=> head (lists !! i) <= head (lists !! j))。

所以我猜你真正想要的是合并一个有序列表的无限列表。这甚至是一项有意义的任务。甚至还有一些使用它的现有代码,在那里为单子列表实现 - 有点难看的语法等。所以这是一个普通列表的版本:

mergeOnSortedHeads :: Ord b => (a -> b) -> [[a]] -> [a]
mergeOnSortedHeads _ [] = []
mergeOnSortedHeads f ([]:xs) = mergeOnSortedHeads f xs
mergeOnSortedHeads f ((x:xs):ys) =
  x : mergeOnSortedHeads f (bury xs ys)
  where
    bury [] ks = ks
    bury js [] = [js]
    bury js ([]:ks) = bury js ks
    bury jj@(j:js) ll@(kk@(k:ks):ls)
      | f j <= f k = jj : ll
      | otherwise = kk : bury jj ls

ghci> take 20 $ mergeOnSortedHeads id $ [[0,4,6], [2,3,9], [3,5..], [8]] ++ map repeat [12..]
[0,2,3,3,4,5,6,7,8,9,9,11,12,12,12,12,12,12,12,12]

顺便说一句:你需要这个做什么?

于 2010-03-07T07:23:49.833 回答
3

好吧,我将忽略您对无限数据进行排序的请求。

要按子列表的长度排序,然后按字典顺序,我们可以很容易地做到这一点。哦,你想删除重复项。

我们将从一个示例开始:

> s
[["a","b"],["a","aa","aaa"],["b","bb","bbb"]]

然后逐步构建程序。

首先按长度排序(使用 Data.Ord.comparing 构建排序体):

> sortBy (comparing length) s
[["a","b"],["a","aa","aaa"],["b","bb","bbb"]]

好的。这看起来很合理。所以让我们连接,然后 sortBy 长度然后 alpha:

> sortBy (comparing length) . nub . concat $ s
["a","b","aa","bb","aaa","bbb"]

如果您的输入已排序。否则,您将需要一个稍微不同的主体来排序。

于 2010-03-07T01:08:17.687 回答
1

这是一个让您在线排序的算法:

它效率不高,但它足够懒惰,即使您对无限列表进行排序,也可以让您进入不同的排序世代。这是一个不错的噱头,但不是很实用。例如对无限列表 [10,9..] 进行排序:

*Main> take 10 $ sortingStream [10,9..] !! 0
[9,8,7,6,5,4,3,2,1,0]
*Main> take 10 $ sortingStream [10,9..] !! 1
[8,7,6,5,4,3,2,1,0,-1]
*Main> take 10 $ sortingStream [10,9..] !! 2
[7,6,5,4,3,2,1,0,-1,-2]
*Main> take 10 $ sortingStream [10,9..] !! 3
[6,5,4,3,2,1,0,-1,-2,-3]
*Main> take 10 $ sortingStream [10,9..] !! 4
[5,4,3,2,1,0,-1,-2,-3,-4]
*Main> take 10 $ sortingStream [10,9..] !! 1000
[-991,-992,-993,-994,-995,-996,-997,-998,-999,-1000]

正如你所看到的,排序改进了每一代。编码:

produce :: ([a] -> [a]) -> [a] -> [[a]]
produce f xs = f xs : (produce f (f xs))


sortingStream :: (Ord a) => [a] -> [[a]]
sortingStream = produce ss

ss :: (Ord a) => [a] -> [a]
ss [] = []
ss [x] = [x]
ss [x,y]    | x <= y = [x,y]
            | otherwise = [y,x]
ss (x:y:xs) | x <= y  =  x: (ss (y:xs))
            | otherwise =  y:(ss (x:xs))
于 2010-05-15T02:49:14.550 回答
1

感谢大家的投入,对于迟到的回复感到抱歉。原来我只是以错误的方式解决问题。我试图做 Yairchu 展示的事情,但我使用内置函数length进行合并,但由于显而易见的原因,长度在无限列表上不起作用。无论如何,我通过排序解决了我的问题,因为我在旅途中创建了列表,而不是最终结果。我想知道还有哪些其他语言提供无限列表?这样一个奇怪但有用的概念。

于 2010-03-10T15:40:15.100 回答
0

是否可以完成很大程度上取决于您输入数据的性质。如果您在看到更长的列表时可以“停止寻找”特定长度的列表,并且每个长度的列表只有有限数量,那么您可以按升序浏览这些长度,对它们进行排序并连接结果。像这样的东西应该工作:

listsUptoLength n xss = takeWhile (\xs -> length xs <= n) $ xss 
listsUptoLength' n [] = []
listsUptoLength' n (xss:xsss) = case listsUptoLength n xss of
    [] -> []
    xss' -> xss' : listsUptoLength' n xsss
listsOfLength n xsss = concatMap (\xss -> (filter (\xs -> length xs == n) xss)) (listsUptoLength' n xsss) 

sortInfinite xsss = concatMap (\n -> sort . nub $ (listsOfLength n xsss)) [0..] 

f xs y = [xs ++ replicate n y | n <- [1..]]
test = [ map (\x -> [x]) ['a'..'e'], f "" 'a', f "" 'b', f "b" 'a', f "a" 'b' ] ++ [f start 'c' | start <- f "" 'a'] 

(这些名字可能会被选为更有启发性:)

您正在使用正则表达式,所以我认为可以使这样的事情起作用;我重复要求更多背景!

于 2010-03-07T12:29:04.450 回答