如何有效地从Erlang的STDIN读取数千行? [英] How to efficiently read thousand of lines from STDIN in Erlang?
问题描述
从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屋!