将两个文件收集到另一个文件

时间:2016-01-14 08:03:30

标签: io prolog

我有两个文件file1.txtfile2.txt,我想在检查两个文件的行后在file3.txt收集它们。

示例:

FILE1.TXT

line 1    T
line 2    F
line 3    T
line 4    T
line 5    F
line 6    F

FILE2.TXT

line 1    T
line 2    T
line 3    F
line 4    T
line 5    F
line 6    T

file3.txt

    file1 
    ********************
    number of line  = 6
    number of true  = 3
    number of false = 3
    ********************
    line 1    T
    line 3    T
    line 4    T

    file2
    ********************
    number of line  = 6
    number of true  = 4
    number of false = 2
    ********************
    line 1    T
    line 2    T
    line 4    T
    line 6    T

对于每个文件,生成的文件应包含一个标题,显示行数,真实行数(T)和假行数(F)。接下来仅打印真实的行。

一些帮助?

2 个答案:

答案 0 :(得分:2)

这是一个粗略的草图,可以帮助您开始使用library(pio)

我们将lines//1定义为我{@ 3}}中的@mat到相关问题“his answer”。然后使用Read a file line by line in Prologtpartition/4编写:

?- prefix_of_t/3(set_prolog_flag      , codes),
   set_prolog_flag(toplevel_print_anon, false).
true.

?- double_quotes(phrase_from_file(_Ls), 'file1.txt'),
   lines(maplist, _Ls, _Rs),
   reverse(tpartition("T"), _Rs, _Ts0, _Fs),
   maplist(reverse, _Ts0, _Ts),
   prefix_of_t(forall(X,_Ts), member('~s~n',[X])).
line 1    T
line 3    T
line 4    T
true.

答案 1 :(得分:1)

您可以按照以下方式执行此操作。我们首先定义谓词merge/2,第一项是必须读取的文件名列表(此处为[file1.txt,file2.txt]),第二项参数是您要写入的文件名(此处为{{ 1}})。现在我们将file3.txt定义为:

merge/2

因此,我们打开一个名为merge(Inp,Outp) :- open(Outp,write,Outs), mergeS(Inp,Outs). 的文件并获取相应的流Outp,然后调用Outs

mergeS/2有两种情况:

  • 所有输入文件都已处理完毕,因此我们可以停止处理并关闭流:

    mergeS/2
  • 我们还需要处理至少一个文件:

    mergeS([],OutS) :-
        close(OutS).
    

    这个谓词的核心显然是mergeS([H|T],OutS) :- open(H,read,InS), atom_chars(FileN,H), process(FileN,InS,OutS), close(InS), mergeS(T,OutS). ,但为了使事情更方便。我们已在process/3

  • 中进行文件处理

接下来,我们的 mergeS 谓词为:

process/3

我们首先使用process(Header,InS,OutS) :- get_lines(InS,Lin,NL,NT,NF), write(OutS,Header),nl(OutS), write(OutS,'********************'),nl(OutS), write(OutS,'number of line = '),write(OutS,NL),nl(OutS), write(OutS,'number of true = '),write(OutS,NT),nl(OutS), write(OutS,'number of false = '),write(OutS,NF),nl(OutS), write(OutS,'********************'),nl(OutS), print_lines(OutS,Lin), nl(OutS). 收集文件的内容。该谓词将同时计算统计数据,如行数,真实数和假数。接下来,我们使用许多get_lines/5write/2语句将统计信息写入输出文件,然后使用谓词nl/1将谓词文件的内容写入print_lines/2

file3.txtget_lines

get_line使用三个累加器来计算统计数据。这是通过初始化三个累加器然后调用get_lines/5来完成的:

get_lines/8

get_lines(Ins,Lin,NL,NT,NF) :- get_lines(Ins,Lin,0,0,0,NL,NT,NF). 是一个递归函数,一次处理一行,确定该行是get_lines/8还是T,更新累加器,并解析下一行。但是我们可能会得到一个空文件。为了使我们的方法更加健壮,我们写道:

F

和递归案例:

get_lines(InS,[],NL,NT,NF,NL,NT,NF) :-
    at_end_of_stream(InS),
    !.

get_lines(InS,[H|T],NL0,NT0,NF0,NL,NT,NF) :- get_line(InS,HCs), inspect(HCs,NL0,NT0,NF0,NL1,NT1,NF1), atom_chars(H,HCs), get_lines(InS,T,NL1,NT1,NF1,NL,NT,NF). 只是读取文件的下一行,并返回一个字符流。它终止于get_line/2(包括但不在结果中)。

'\n'

<强> get_line(InS,[]) :- at_end_of_stream(InS), !. get_line(InS,[H|T]) :- get_char(InS,H), H \= '\n', !, get_line(InS,T). get_line(_,[]).

现在我们仍然需要使用inspect/7检查我们的行。我们再次使用三个累加器(正如您已经根据inspect/7的实现而猜测的那样)。首先,我们获取该行的最后一个字符。如果不存在这样的字符,则统计信息不会更改(可能会在某处引入空行)。否则,我们会使用get_lines/8获取最后一个字符,并使用last/2进行检查:

inspect_last/7

inspect(L,NL0,NT0,NF0,NL,NT,NF) :- last(L,LL), !, NL is NL0+1, inspect_last(LL,NT0,NF0,NT,NF). inspect(_,NL0,NT,NF,NL1,NT,NF) :- !, NL1 is NL0+1. 确定最后一个字符是inspect_lastT还是其他字符,并相应地更新累加器:

F

<强> inspect_last('T',NT0,NF,NT1,NF) :- !, NT1 is NT0+1. inspect_last('F',NT,NF0,NT,NF1) :- !, NF1 is NF0+1. inspect_last(_,NT,NF,NT,NF).

最后我们仍然需要将文件打印到输出。这是使用print_lines/2完成的,这很简单:

print_lines/2

完整代码

完整代码:

print_lines(_,[]) :-
    !.
print_lines(OutS,[H|T]) :-
    write(OutS,H),
    nl(OutS),
    print_lines(OutS,T).

如果现在查询:

merge(Inp,Outp) :-
    open(Outp,write,Outs),
    mergeS(Inp,Outs).

mergeS([],OutS) :-
    close(OutS).

mergeS([H|T],OutS) :-
    open(H,read,InS),
    atom_chars(FileN,H),
    process(FileN,InS,OutS),
    close(InS),
    mergeS(T,OutS).

process(Header,InS,OutS) :-
    get_lines(InS,Lin,NL,NT,NF),
    write(OutS,Header),nl(OutS),
    write(OutS,'********************'),nl(OutS),
    write(OutS,'number of line  = '),write(OutS,NL),nl(OutS),
    write(OutS,'number of true  = '),write(OutS,NT),nl(OutS),
    write(OutS,'number of false = '),write(OutS,NF),nl(OutS),
    write(OutS,'********************'),nl(OutS),
    print_lines(OutS,Lin),
    nl(OutS).

get_lines(Ins,Lin,NL,NT,NF) :-
    get_lines(Ins,Lin,0,0,0,NL,NT,NF).

get_lines(InS,[],NL,NT,NF,NL,NT,NF) :-
    at_end_of_stream(InS),
    !.
get_lines(InS,[H|T],NL0,NT0,NF0,NL,NT,NF) :-
    get_line(InS,HCs),
    inspect(HCs,NL0,NT0,NF0,NL1,NT1,NF1),
    atom_chars(H,HCs),
    get_lines(InS,T,NL1,NT1,NF1,NL,NT,NF).

get_line(InS,[]) :-
    at_end_of_stream(InS),
    !.
get_line(InS,[H|T]) :-
    get_char(InS,H),
    H \= '\n',
    !,
    get_line(InS,T).
get_line(_,[]).

inspect(L,NL0,NT0,NF0,NL,NT,NF) :-
    last(L,LL),
    !,
    NL is NL0+1,
    inspect_last(LL,NT0,NF0,NT,NF).
inspect(_,NL0,NT,NF,NL1,NT,NF) :-
    !,
    NL1 is NL0+1.

inspect_last('T',NT0,NF,NT1,NF) :-
    !,
    NT1 is NT0+1.
inspect_last('F',NT,NF0,NT,NF1) :-
    !,
    NF1 is NF0+1.
inspect_last(_,NT,NF,NT,NF).

print_lines(_,[]) :-
    !.
print_lines(OutS,[H|T]) :-
    write(OutS,H),
    nl(OutS),
    print_lines(OutS,T).

名为?- merge(["file1.txt","file2.txt"],"file3.txt"). true. 的文件由内容构建:

file3.txt

这或多或少是你想要的。如果发生进一步的错误,请评论。

修改

不知何故,我没有让你想要过滤行,只显示真实的行(file1.txt ******************** number of line = 6 number of true = 3 number of false = 3 ******************** line 1 T line 2 F line 3 T line 4 T line 5 F line 6 F file2.txt ******************** number of line = 6 number of true = 4 number of false = 2 ******************** line 1 T line 2 T line 3 F line 4 T line 5 F line 6 T )。您只需修改T

即可
get_lines(InS,[],NL,NT,NF,NL,NT,NF) :-
    at_end_of_stream(InS),
    !.
get_lines(InS,Res,NL0,NT0,NF0,NL,NT,NF) :-
    get_line(InS,HCs),
    inspect(HCs,NL0,NT0,NF0,NL1,NT1,NF1),
    atom_chars(H,HCs),
    ( NT1 > NT0
    -> Res =[H|T]
    ; Res = T
    ),
    get_lines(InS,T,NL1,NT1,NF1,NL,NT,NF).

(在内容改变的地方添加了粗体字)

这不是最优雅的方式,但它可能是最短的修复方法。

现在我机器上的文件显示:

get_lines/7