如何以自然顺序有效地构建erlang列表?

时间:2014-09-16 17:13:52

标签: erlang

Programming Erlang一书中,有一些示例伪代码显示了一种模式,可以有效地将元素添加到列表的头部:

some_function([H|T], ..., Result, ...) ->
    H1 = ... H ...,
    some_function(T, ..., [H1|Result], ...);
some_function([H|T], ..., Result, ...) ->
    {..., Result, ...}.

我仍然习惯于函数式编程,所以上面的例子对我来说有点太抽象了。

我认为如果我可以剖析的模式的具体实现会更容易理解。

问题:有人可以提供这种模式的简单具体实现吗?

3 个答案:

答案 0 :(得分:2)

假设我们想要一个与uniq命令类似的函数。 该函数获取元素列表并返回一个列表,其中所有连续出现的元素都被该元素的单个匹配项替换。 其中一种可能的方法如下:

uniq(L) ->
    uniq(L, []).

uniq([], Acc) ->
    lists:reverse(Acc);
uniq([H, H | T], Acc) ->
    uniq([H | T], Acc);
uniq([H | T], Acc) ->
    uniq(T, [H | Acc]).

我们通过在Acc列表的头部插入新元素(最便宜的插入成本)来构建累加器,一旦完成,我们将整个列表反转以获得元素的初始顺序。

我们两次“访问”初始列表的一些元素,但总成本仍然是线性的,即仅取决于初始列表的元素数量。

答案 1 :(得分:2)

这需要一个分解列表,即

[[],[2],[3],[2,2],[5],[2,3],[7],[2,2,2],etc...]

并删除所有素数。

remove_primes([HD|TL], Results) -> 

    case length(HD) of
           0 -> % You're at 1
                  remove_primes (TL , Results);
           1 -> % Its a prime, remove it, and keep going
                  remove_primes( TL , Results) ;
           _ -> % its not prime, leave it in and keep going.  
                  remove_primes(TL, [ HD | Results]) 
    end;

remove_primes([], Result) -> 
                 {Result}.

Joe Armstrong也提到了这个结构,它是走一个列表并将一个函数应用于列表中每个元素的标准结构。在这种情况下,我希望根据其内容区别对待每个元素。

在实践中,使用地图,过滤器等要容易得多,所以我相信你会更频繁地看到它 - 但是你似乎知道,了解基础知识对于成为一名熟练的功能性程序员至关重要。

希望集中有关“以自然顺序构建列表”的信息,是否有人知道为什么函数级别的模式匹配,工作,'但解包'变量不? (比较一下)(它不起作用)

remove_primes(Factorized_List, Results) -> 
    [HD|TL] = Factorized_List, % unpack the list   <-------------

        case length(HD) of
               0 -> % You're at 1
                  remove_primes (TL , Results);
           1 -> % Its a prime, remove it, and keep going
                  remove_primes( TL , Results) ;
           _ -> % its not prime, leave it in and keep going.  
                  remove_primes(TL, [HD|Results]) 
        end;

remove_primes([], Result) -> 
                 {Result}.

我相信这会带来更易读的代码,但它似乎不起作用。

-Rc

答案 2 :(得分:1)

这是我可以让你的模式执行的唯一方法:

some_func([H|T], 4, Result, 4) -> 
    H1 = H * 2,
    some_func(T, 3, [H1|Result], 4); 
some_func([H|T], 3, Result, _) ->
    {H, Result, T}.

--output:--

25> a:some_func([1, 2, 3], 4, [], 4).  
{2,[2],[3]}

......没有任何用处。

伪代码中的模式对我来说毫无意义,所以我会在你的困惑中加入你。

这是另一次尝试:

some_func([H|T], [_|T2], Result, Y) -> 
    H1 = H * Y,
    some_func(T, T2, [H1|Result], Y); 
some_func([H|T], [], Result, _) ->
    {H, Result, T}.


--output:--
34> a:some_func([1, 2, 3, 4], [one, two, three], [], 2).
{4,[6,4,2],[]}