2011-06-08 66 views
0

我有一个文本文件,这样行许多1000,这是类的描述与括号括起来解析“说明(标记)”,以“说明,标签”

Chemicals (chem) 
Electrical (elec) 

我的关键字更好的办法需要将这些行逗号分隔值转换就像这样:

Chemicals, chem 
Electrical, elec 

我现在用的就是这样的:

lines = line.gsub!('(', ',').gsub!(')', '').split(',') 

我想知道是否有更好的方法来做到这一点。

留给后人,这是完整的代码(基于答案)

require 'rubygems' 
require 'csv' 

csvfile = CSV.open('output.csv', 'w') 
File.open('c:/categories.txt') do |f| 
    f.readlines.each do |line| 
    (desc, cat) = line.split('(') 
    desc.strip! 
    cat.strip! 
    csvfile << [desc, cat[0,cat.length-1]] 
    end 
end 
+0

为什么你在最后使用他拆分方法?将实际创建一个像'[描述,关键词]' – robertodecurnex 2011-06-08 14:08:21

+0

@NeX数组通过创建一个数组,我可以做一个csvfile <<线,其中csvfile是CSV.open,将采取一切逃跑的照顾。 – 2011-06-08 17:51:53

+0

@sawa你是对的。多年来向初学者解释的东西让我习惯于用圆括号,大括号,尖括号和方括号来表示。 – 2011-06-08 17:54:16

回答

2

尝试是这样的:

line.sub!(/ \((\w+)\)$/, ', \1') 

\1将与给定的正则表达式的第一场比赛被替换(在这种情况下,它将始终是category关键字)。所以它将基本上改变(chem), chem

让我们用一个文本文件中创建一个例子:

lines = [] 
File.open('categories.txt', 'r') do |file| 
    while line = file.gets 
    lines << line.sub(/ \((\w+)\)$/, ', \1') 
    end 
end 

基于问题的更新,我可以提出这样的:

require 'csv' 

csv_file = CSV.open('output.csv', 'w') 

File.open('c:/categories.txt') do |f| 
    f.each_line {|c| csv_file << c.scan(/^(.+) \((\w+)\)$/)} 
end 

csv_file.close 
+0

提供的代码不会在描述和关键字之间插入逗号。但是谢谢你的努力。 – 2011-06-09 03:38:21

+0

改为接受的答案基准 – 2011-06-12 17:02:17

-1

一无所知红宝石,但很容易在PHP

preg_match_all('~(.+)\((.+)\)~','Chemicals (chem)',$m); 

$result = $m[1].','.$m[2]; 
1

从Ruby 1.9开始,您可以在一个方法调用中执行它:

str = "Chemicals (chem)\n" 
mapping = { ' (' => ', ', 
      ')' => ''} 

str.gsub(/ \(|\)/, mapping) #=> "Chemicals, chem\n" 
1

在Ruby中,一个更清洁,更高效,方式做到这一点是:

description, tag = line.split(' ', 2) # split(' ', 2) will return an 2 element array of 
             # the all characters up to the first space and all characters after. We can then use 
             # multi assignment syntax to assign each array element in a different local variable 
tag = tag[1, (tag.length - 1) - 1] # extract the inside characters (not first or last) of the string 
new_line = description << ", " << tag # rejoin the parts into a new string 

这将是计算速度(如果你有很多行),因为它使用直接的字符串操作,而不是正则表达式。

+0

@hundredwatt后,速度是很重要的。 – 2011-06-08 17:55:47

+0

说得太快。有空格的词,如“染料和中间体”。我已经修改在分裂“(”和从所述第一项目和第二项目中删除最后一个字符的例子中 – 2011-06-08 18:09:19

+2

这既是不太明显,也比使用一个正则表达式慢。当我使用测试它针对“化学品(化学)” Ruby 1.9,它需要NeX's或者steenslag的解决方案的两倍以上。“ – 2011-06-08 18:11:11

0

无需操纵字符串。只需获取数据并将其输出到CSV文件即可。 假设你有这样的数据:

化工(化学)

电气(ELEC)

染料&中间体(染料)

这应该工作:

File.open('categories.txt', 'r') do |file| 
    file.each_line do |line| 
    csvfile << line.match(/^(.+)\s\((.+)\)$/) { |m| [m[1], m[2]] } 
    end 
end 
0

@ 100watt答案中与讨论相关的基准:

require 'benchmark' 

line = "Chemicals (chem)" 

# @hundredwatt 
puts Benchmark.measure { 
    100000.times do 
    description, tag = line.split(' ', 2) 
    tag = tag[1, (tag.length - 1) - 1] 
    new_line = description << ", " << tag 
    end 
} # => 0.18 

# NeX 
puts Benchmark.measure { 
    100000.times do 
    line.sub!(/ \((\w+)\)$/, ', \1') 
    end 
} # => 0.08 

# steenslag 
mapping = { ' (' => ', ', 
    ')' => ''} 
puts Benchmark.measure { 
    100000.times do 
    line.gsub(/ \(|\)/, mapping) 
    end 
} # => 0.08 
+0

每天都在学习新东西! – 2011-06-12 17:00:55