繁体   English   中英

如何找出给定元素存在的组的大小?

[英]How can I find out the size of the group a given element exists in?

如果我有这样的列表:

lst = [4,4,4,5,3,3,9]

我可以用group来创建它: [[4,4,4],[5],[3,3],[9]]

如果我有一个指向列表的索引, 例如i = 4 ,它指向前3元素,我怎样才能最好地编写一个获取列表和索引的函数,并返回索引所指向的组的大小(在这种情况下,2,3s组的长度)?

我知道我可以非常强制地写出来,而且我也可以用map length . group来拼凑一些东西map length . group map length . group并计算在查找索引时我通过的map length . group数,但在我看来,必须有一个更好的方法来执行此操作。 欢迎所有建议。

这是一个非常明确的解决方案,所以我可以解释每一步。

制作分组列表:

lst = [4,4,4,5,3,3,9]
lst1 = group lst

接下来,用长度替换组:

lst2 = map length lst1

这给了我们lst2 = [3,1,2,1]

现在用长度列表替换长度,该列表也包含每个位置的长度:

lst3 = map (\l -> replicate l l) lst2

现在我们有lst3 = [[3,3,3],[1],[2,2],[1]] ,这几乎是我们需要的,但我们不想要内部结构:

lst4 = concat lst3

现在我们有一些与原始列表相同的长度,但每个位置的组长度而不是原始值。 所以lst4!!4 = 2

该解决方案使用评论中的想法简化了我的原始解决方案。

正如该评论中指出的那样,还有一些调整是可能的 - 将两个mapconcat作为concatMap ,并在Monad(->) r实例中使用join来“简化” \\l -> replicate ll ,为整个管道提供:

concatMap (join replicate . length) . group $ lst

如果你有一个计算累积和的函数,那么你可以使它相当简单:

cumsum :: Num a => [a] -> [a]
cumsum xs = go xs 0
    where
        go [] _ = []
        go (x:xs) i = let n = x + i in n : go xs n

groupSizeAt :: [[a]] -> Int -> Int
groupSizeAt xs i =
    let groups = zip xs $ cumsum $ map length xs
        targetGroup = head $ dropWhile ((<= i) . snd) groups
    in length $ fst targetGroup

这背后的逻辑是计算组的长度的累积和,然后丢弃组,直到这个累积和大于你正在搜索的索引,然后抓住第一个,丢弃累积和,并计算长度再次。 有一些冗余,但对于小组来说没有什么是太贵的(如果您的组大小在100或1000的数量级,您可能想要修改它以避免必须计算目标组的长度两次)

如果您实际上不需要这些组,只需要您的结果大小,请查看以下内容:

help :: Int -> [Int] -> Int
help i xs = let val = xs !! i in 
    (length . takeWhile (val==) . dropWhile (val/=)) xs

size :: Int -> [Int] -> Int
size i xs = if ( i>0 && xs !! (i-1) == xs !! i) 
            then size (i-1) xs 
            else help i xs

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM