如何有效地从Erlang的STDIN读取数千行? [英] How to efficiently read thousand of lines from STDIN in Erlang?

查看:90
本文介绍了如何有效地从Erlang的STDIN读取数千行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从STDIN读取数千行时,我偶然发现了一个问题。在我发现针对此问题的一些测试之前,这本来是一个虚构的边缘案例。需要从STDIN读取上千行。起初我以为我的算法不是最佳算法,只是偶然地发现,只有没有任何计算的读取行才能使测试时间浪费一半。

I've stumbled upon an issue when reading thousands of lines from STDIN. This would have been an imaginary edge case until I found out that some tests for this problem require reading thousand of lines from STDIN. At first I thought that my algorithms were not optimal, and only by accident I've found out that only reading lines without any computations could make half of the test time out.

此处的部分代码超时:

process_queries(0, _) -> ok;
process_queries(N, A) -> 
    case io:fread("", "~s~d~d") of
        {ok, _} -> process_queries(N - 1, A)
        %{ok, ["Q", L, R]} -> process_queries(N - 1, apply_q(L, R, A));
        %{ok, ["U", Idx, Val]} -> process_queries(N - 1, apply_u(Idx, Val, A))
    end
.

我故意留下评论以表明所有计算均被禁用。因此,在给出 N = 7984 的情况下,此代码超时。

I deliberately left comments to show that all the computations were disabled. So this code timed out given N=7984.

有没有更好的方法来读取和处理数千行

Is there a better way of reading and processing thousands lines from STDIN in Erlang?


  • io:get_line 一次只能得到一行。

  • io:get_chars 要求您知道要获得多少个字符。

  • io:get_line gets only one line a time.
  • io:get_chars requires you to know how many character to get.

推荐答案

我的解决方案有节选。

There is an excerpt from my solution. There are few tricks how to do it really efficient.

read_command(CP) ->
    {ok, Line} = file:read_line(standard_io),
    [C, A, B] = binary:split(Line, CP, [global, trim_all]),
    {case C of <<"Q">> -> 'Q'; <<"U">> -> 'U' end,
     binary_to_integer(A),
     binary_to_integer(B)}.

read_commands(N, CP) ->
    [ read_command(CP) || _ <- lists:seq(1, N) ].

execute(Array, L) ->
    lists:foldl(fun({'Q', F, T}, A) ->
                        {Val, A2} = query(A, F, T),
                        file:write(standard_io, [integer_to_binary(Val), $\n]),
                        A2;
                   ({'U', I, V}, A) ->
                        update(A, I, V)
                end, Array, L).

read_int_line(CP) ->
    {ok, Line} = file:read_line(standard_io),
    [binary_to_integer(X) || X <- binary:split(Line, CP, [global, trim_all])].

main() ->
    ok = io:setopts([binary]),
    CP = binary:compile_pattern([<<" ">>, <<$\n>>]),
    [N] = read_int_line(CP),
    L = read_int_line(CP),
    N = length(L),
    [K] = read_int_line(CP),
    execute(init(L), read_commands(K, CP)).

您必须编写自己的 init / 1 update / 3 query / 3 当然。

You have to write your own init/1, update/3 and query/3 of course.

这篇关于如何有效地从Erlang的STDIN读取数千行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆