运维开发网

优雅的方式在Ruby中逐行按字母顺序合并2个文本文件

运维开发网 https://www.qedev.com 2020-07-29 20:36 出处:网络 作者:运维开发网整理
我有2个日志文件,它们都包含按时间顺序以日期戳开头的文本行.我想将两个文件合并到一个文件中,该文件包含按时间顺序合并的两个文件中的所有行.由于日期戳的布局,在这种情况下按时间顺序排列与字母相同. 我编写了一个执行此操作的Ruby脚本并且工作正常,但我只是学习语言的Ruby新手,我真正喜欢Ruby的一件事就是语法糖和代码的可读性.而且我不禁觉得我的解决方案非常笨重,而且肯定有更好的方法可以解决同样的
我有2个日志文件,它们都包含按时间顺序以日期戳开头的文本行.我想将两个文件合并到一个文件中,该文件包含按时间顺序合并的两个文件中的所有行.由于日期戳的布局,在这种情况下按时间顺序排列与字母相同.

我编写了一个执行此操作的Ruby脚本并且工作正常,但我只是学习语言的Ruby新手,我真正喜欢Ruby的一件事就是语法糖和代码的可读性.而且我不禁觉得我的解决方案非常笨重,而且肯定有更好的方法可以解决同样的问题.我并不需要在算法上更好地寻找,但在句法上. Ruby似乎对几乎所有东西都有单线解决方案,所以也许这样的问题也是如此.

if ARGV.length != 2
    puts "Wrong number of arguments. Expected 2 arguments (path to 2 log files to be merged)"
end

merged_file = File.open("merge_out.txt", "w")
file1 = File.open(ARGV[0], "r")
file2 = File.open(ARGV[1], "r")

line1 = file1.gets
line2 = file2.gets

while (line1 != nil or line2 !=nil)
    if line1 == nil
        # no more line1 so write line2 and proceed file2
        merged_file.puts line2
        line2 = file2.gets        
    elsif line2 == nil
        # no more line2 so write line1 and proceed file1
        merged_file.puts line1
       line1 = file1.gets          
    else 
        comp = line1<=>line2
        #both lines present, write and proceed the (alphabetically) smaller one 
        #as this is the one with the earlier time stamp
        if comp == -1
            merged_file.puts line1
            line1 = file1.gets              
        else
            merged_file.puts line2
            line2 = file2.gets           
         end    
    end       
end

那么,如何才能更优雅地完成这项工作?

有时添加维度会使解决方案更漂亮.本质上,将file1,file2变量转换为数组[file1,file2],这会打开很多Ruby Array语法,执行您已编码到初始解决方案中的测试.

if ARGV.length < 2
    puts "Wrong number of arguments. Expected 2 or more files to merge."
end

merged_file = File.open("merge_out.txt", "w")

files = ARGV.map { |filename| File.open( filename, "r") }

lines = files.map { |file| file.gets }

while lines.any?
    next_line = lines.compact.min
    file_id = lines.index( next_line )
    merged_file.print next_line
    lines[ file_id ] = files[ file_id ].gets
end

因此,这不仅更短,而且副作用可以同时处理更多输入文件.虽然如果你不需要,只需改回第一次检查.

扫码领视频副本.gif

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号