2016-11-15 57 views
0

我需要帮助,我使用Ruby。我有一个包含下一个文本文件:解析和构建文本文件

Head 1 
a 10 
b 14 
c 15 
d 16 
e 17 
f 88 
Head 4 
r 32 
t 55 
s 79 
r 22 
t 88 
y 53 
o 78 
p 90 
m 44 
Head 53 
y 22 
b 33 
Head 33 
z 11 
d 66 
v 88 
b 69 
Head 32 
n 88 
m 89 
b 88 

我想解析并将此文件结构到下一个平面。我想获得下一个数据:

Head 1, f 88 
Head 4, t 88 
Head 33, v 88 
Head 32, n 88 
Head 32, b 88 

请告诉我如何在红宝石上做这样的代码?

我觉得首先我必须把它在阵列中的所有行:

lines = Array.new 
File.open('C:/file/file.txt', 'r').each { |line| lines << line } 

但我要做什么?

谢谢!

+2

你想抓住所有具有“88”值的东西吗?这个问题还不清楚。另外,请告诉我们你已经尝试了什么。 – mudasobwa

+0

@il_raffa感谢编辑 – Misha1991

+0

@Mudasobwa是的,我想选择所有记录与88和他们的头文件 – Misha1991

回答

1

如果@mudasobwa问题的答案是“你想抓住所有有价值的东西吗?”这是解决方案

lines = File.open("file.txt").to_a 
lines.map!(&:chomp) # remove line breaks 

current_head = "" 
res = [] 

lines.each do |line| 
    case line 
    when /Head \d+/ 
    current_head = line 
    when /\w{1} 88/ 
    res << "#{current_head}, #{line}" 
    end 
end 

puts res 
+0

是的,你会的!谢谢! – Misha1991

+0

这是最好的方法,imo。我有几点建议。 1.使用'File.foreach('file.txt')。with_object([])do | line,res |'来代替所有通过'lines.each do | line |'的行。 'with_object([])'初始化'res'并导致块返回'res'。 2.不需要初始化'current_head'。 3。'\ w {1}'与'\ w'相同,但您可能想要更具体一些,比如使用'[[:lower:]]'或'[[:lower:]] +'。 4.在'when/Head \ d + /'后写下'head = line;当/ [[:lower:]] + \ s + 88 /; res <<“#{head.chomp},#{line.chomp}”; end'。 –

+0

@CarySwoveland你是对的,我已经写了一个初学者级的解决方案,但是你有专业的解决方案。 –

1

我写你的数据文件“临时”:

首先定义用于提取感兴趣的文件的行正则表达式。

r =/
    Head\s+\d+  # match 'Head', > 0 spaces, ?= 1 digits in capture group 1 
    |     # or 
    [[:lower:]]+\s+88 # match > 0 lower case letters, > 0 spaces, '88' 
    /xm    # free-spacing regex definition and multi-line modes 

现在对该文件执行以下操作。

File.read('temp').scan(r). 
        slice_before { |line| line.start_with?('Head ') }. 
        reject { |a| a.size == 1 }. 
        flat_map { |head, *rest| [head].product(rest) }. 
        map { |a| "%s, %s" % a } 
    #=> ["Head 1, f 88", "Head 4, t 88", "Head 33, v 88", 
    # "Head 32, n 88", "Head 32, b 88"] 

步骤如下。

a = File.read('temp').scan(r) 
    #=> ["Head 1", "f 88", "Head 4", "t 88", "Head 53", "Head 33", 
    # "v 88", "Head 32", "n 88", "b 88"] 
b = a.slice_before { |line| line.start_with?('Head') } 
    #=> #<Enumerator: #<Enumerator::Generator:0x007ffd218387b0>:each> 

我们可以看到,通过将枚举b通过将其转换到一个阵列产生的元素。

b.to_a 
    #=> [["Head 1", "f 88"], ["Head 4", "t 88"], ["Head 53"], 
    # ["Head 33", "v 88"], ["Head 32", "n 88", "b 88"]] 

现在从b中删除所有大小为1的数组。

c = b.reject { |a| a.size == 1 } 
    #=> [["Head 1", "f 88"], ["Head 4", "t 88"], ["Head 33", "v 88"], 
    # ["Head 32", "n 88", "b 88"]] 

接下来我们使用Enumerable#flat_mapArray#product每个“头”与以下所有线路为此88\n(前下一个“头”或文件的末尾)相关联。

d = c.flat_map { |head, *rest| [head].product(rest) } 
    #=> [["Head 1", "f 88"], ["Head 4", "t 88"], ["Head 33", "v 88"], 
    # ["Head 32", "n 88"], ["Head 32", "b 88"]] 

最后,将d的每个元素转换为一个字符串。

d.map { |a| "%s, %s" % a } 
    #=> ["Head 1, f 88", "Head 4, t 88", "Head 33, v 88", 
    # "Head 32, n 88", "Head 32, b 88"]