所以基本上,如果我有一个(有限的或无限的)字符串列表(有限或无限)列表,是否可以先按长度排序列表,然后按字典顺序排序,不包括重复项?样本输入/输出将是:
输入:
[[“a”,“b”,...],[“a”,“aa”,“aaa”],[“b”,“bb”,“bbb”,...], ...]
输出:
[“a”,“b”,“aa”,“bb”,“aaa”,“bbb”,...]
我知道输入列表不是有效的haskell表达式,但假设有类似的输入。我尝试使用合并算法,但它倾向于挂在我给它的输入上。有人可以解释并展示一个可以做到这一点的体面分类功能吗?如果没有这样的功能,你能解释一下原因吗?
如果有人不理解我对排序顺序的意思,我的意思是首先排序最短的字符串,如果一个或多个字符串长度相同,则使用<操作
谢谢!
答案 0 :(得分:15)
最终,你无法对无限列表进行排序,因为列表尾部的项目可以一直渗透到结果的前面,因此在看到之前你无法完成对无限列表的排序。最后一项,但你的清单是无限的,所以你永远不会到达那里。
您甚至可以尝试对无限列表进行排序的唯一方法是需要对列表中的居民进行约束。如果列表项的值来自well-founded set并且列表的内容是唯一的,那么您至少可以在返回元素列表的初始元素方面取得一些进展。例如,如果列表具有不同的自然数,您可以返回您看到的前0,然后是第1个,等等,但是在您看到2之前,无论在列表中有多远,您都无法取得任何进展。你去了。最后,如果你曾经跳过集合中的元素,因为它不存在于源代码中,那么在你掌握了整个输入之前,你将停止生成新的输出元素。
你可以用字符串做同样的事情,因为它们是有根据的,但如果你计划返回所有可能的字符串,这甚至是可行的。
简而言之,如果您需要这个,那么您将以错误的方式解决您遇到的问题。这不是您想要使用的任何解决方案的易处理路径。
正如yairchu指出的那样,合并有限数量的有序无限列表可以正常工作。
答案 1 :(得分:9)
通常,无法对无限列表进行排序。因为最小的项目可能处于无限的位置,我们必须在输出之前找到它。
Merging无限排序列表是可能的。
通常,合并无限的排序列表列表是不可能的。出于同样的原因,对它们进行排序是。
合并一个无限的排序列表列表,这些列表按头部排序(forall i j。i < j
=&gt; head (lists !! i) <= head (lists !! j)
)是可能的。
所以我猜你真正想要的是合并排序列表的无限列表。这甚至是一项有意义的任务。有甚至some existing code使用它,为那里的monadic列表实现 - 有点丑陋的语法等等。所以这里是普通列表的版本:
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]
顺便问一下:你需要什么呢?
答案 2 :(得分: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"]]
确定。这看起来很合理。所以让我们只是concat,然后sortBy长度然后alpha:
> sortBy (comparing length) . nub . concat $ s
["a","b","aa","bb","aaa","bbb"]
如果您的输入已排序。否则你需要一个不同的身体来sortBy。
答案 3 :(得分:1)
感谢大家的投入,并对迟到的回复表示歉意。原来我只是以错误的方式解决问题。我试图做Yairchu所展示的但是我使用内置函数length
来进行合并,但由于显而易见的原因,长度在无限列表中不起作用。无论如何,我通过排序解决了我的问题,因为我在旅途中创建了列表,而不是最终结果。我想知道其他语言提供无限列表?这种奇怪但有用的概念。
答案 4 :(得分: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))
答案 5 :(得分: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']
(可能会选择这些名称更具启发性:)
我猜测你正在使用正则表达式,所以我认为这样的事情可以起作用;我重复了更多背景的请求!