2016-11-15 88 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"]