lib/csv.rb: refactor and optimize. This change
includes the patch from marshall-lee. close #1168 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59671 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
a2f5275e0b
commit
1a1930180c
47
lib/csv.rb
47
lib/csv.rb
@ -242,7 +242,7 @@ class CSV
|
|||||||
@row = if headers.size >= fields.size
|
@row = if headers.size >= fields.size
|
||||||
headers.zip(fields)
|
headers.zip(fields)
|
||||||
else
|
else
|
||||||
fields.zip(headers).map { |pair| pair.reverse! }
|
fields.zip(headers).each(&:reverse!)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -267,7 +267,7 @@ class CSV
|
|||||||
|
|
||||||
# Returns the headers of this row.
|
# Returns the headers of this row.
|
||||||
def headers
|
def headers
|
||||||
@row.map { |pair| pair.first }
|
@row.map(&:first)
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -451,21 +451,23 @@ class CSV
|
|||||||
#
|
#
|
||||||
def fields(*headers_and_or_indices)
|
def fields(*headers_and_or_indices)
|
||||||
if headers_and_or_indices.empty? # return all fields--no arguments
|
if headers_and_or_indices.empty? # return all fields--no arguments
|
||||||
@row.map { |pair| pair.last }
|
@row.map(&:last)
|
||||||
else # or work like values_at()
|
else # or work like values_at()
|
||||||
headers_and_or_indices.inject(Array.new) do |all, h_or_i|
|
all = []
|
||||||
all + if h_or_i.is_a? Range
|
headers_and_or_indices.each do |h_or_i|
|
||||||
|
if h_or_i.is_a? Range
|
||||||
index_begin = h_or_i.begin.is_a?(Integer) ? h_or_i.begin :
|
index_begin = h_or_i.begin.is_a?(Integer) ? h_or_i.begin :
|
||||||
index(h_or_i.begin)
|
index(h_or_i.begin)
|
||||||
index_end = h_or_i.end.is_a?(Integer) ? h_or_i.end :
|
index_end = h_or_i.end.is_a?(Integer) ? h_or_i.end :
|
||||||
index(h_or_i.end)
|
index(h_or_i.end)
|
||||||
new_range = h_or_i.exclude_end? ? (index_begin...index_end) :
|
new_range = h_or_i.exclude_end? ? (index_begin...index_end) :
|
||||||
(index_begin..index_end)
|
(index_begin..index_end)
|
||||||
fields.values_at(new_range)
|
all.concat(fields.values_at(new_range))
|
||||||
else
|
else
|
||||||
[field(*Array(h_or_i))]
|
all << field(*Array(h_or_i))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return all
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
alias_method :values_at, :fields
|
alias_method :values_at, :fields
|
||||||
@ -835,11 +837,10 @@ class CSV
|
|||||||
if @mode == :row or @mode == :col_or_row # by index
|
if @mode == :row or @mode == :col_or_row # by index
|
||||||
@table.delete_if(&block)
|
@table.delete_if(&block)
|
||||||
else # by header
|
else # by header
|
||||||
to_delete = Array.new
|
deleted = []
|
||||||
headers.each_with_index do |header, i|
|
headers.each do |header|
|
||||||
to_delete << header if block[[header, self[header]]]
|
deleted << delete(header) if block[[header, self[header]]]
|
||||||
end
|
end
|
||||||
to_delete.map { |header| delete(header) }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
self # for chaining
|
self # for chaining
|
||||||
@ -1188,11 +1189,11 @@ class CSV
|
|||||||
# The <tt>:row_sep</tt> +option+ defaults to <tt>$INPUT_RECORD_SEPARATOR</tt>
|
# The <tt>:row_sep</tt> +option+ defaults to <tt>$INPUT_RECORD_SEPARATOR</tt>
|
||||||
# (<tt>$/</tt>) when calling this method.
|
# (<tt>$/</tt>) when calling this method.
|
||||||
#
|
#
|
||||||
def self.generate_line(row, encoding: nil, **options)
|
def self.generate_line(row, **options)
|
||||||
options = {row_sep: $INPUT_RECORD_SEPARATOR}.merge(options)
|
options = {row_sep: $INPUT_RECORD_SEPARATOR}.merge(options)
|
||||||
str = String.new
|
str = String.new
|
||||||
if encoding
|
if options[:encoding]
|
||||||
str.force_encoding(encoding)
|
str.force_encoding(options[:encoding])
|
||||||
elsif field = row.find { |f| not f.nil? }
|
elsif field = row.find { |f| not f.nil? }
|
||||||
str.force_encoding(String(field).encoding)
|
str.force_encoding(String(field).encoding)
|
||||||
end
|
end
|
||||||
@ -1262,16 +1263,16 @@ class CSV
|
|||||||
# * truncate()
|
# * truncate()
|
||||||
# * tty?()
|
# * tty?()
|
||||||
#
|
#
|
||||||
def self.open(*args, **options)
|
def self.open(filename, mode="r", **options)
|
||||||
# wrap a File opened with the remaining +args+ with no newline
|
# wrap a File opened with the remaining +args+ with no newline
|
||||||
# decorator
|
# decorator
|
||||||
file_opts = {universal_newline: false}.merge(options)
|
file_opts = {universal_newline: false}.merge(options)
|
||||||
|
|
||||||
begin
|
begin
|
||||||
f = File.open(*args, file_opts)
|
f = File.open(filename, mode, file_opts)
|
||||||
rescue ArgumentError => e
|
rescue ArgumentError => e
|
||||||
raise unless /needs binmode/ =~ e.message and args.size == 1
|
raise unless /needs binmode/ =~ e.message and mode == "r"
|
||||||
args << "rb"
|
mode = "rb"
|
||||||
file_opts = {encoding: Encoding.default_external}.merge(file_opts)
|
file_opts = {encoding: Encoding.default_external}.merge(file_opts)
|
||||||
retry
|
retry
|
||||||
end
|
end
|
||||||
@ -1727,7 +1728,7 @@ class CSV
|
|||||||
# converted field or the field itself.
|
# converted field or the field itself.
|
||||||
#
|
#
|
||||||
def convert(name = nil, &converter)
|
def convert(name = nil, &converter)
|
||||||
add_converter(:converters, self.class::Converters, name, &converter)
|
add_converter(:@converters, self.class::Converters, name, &converter)
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -1742,7 +1743,7 @@ class CSV
|
|||||||
# effect.
|
# effect.
|
||||||
#
|
#
|
||||||
def header_convert(name = nil, &converter)
|
def header_convert(name = nil, &converter)
|
||||||
add_converter( :header_converters,
|
add_converter( :@header_converters,
|
||||||
self.class::HeaderConverters,
|
self.class::HeaderConverters,
|
||||||
name,
|
name,
|
||||||
&converter )
|
&converter )
|
||||||
@ -2176,7 +2177,7 @@ class CSV
|
|||||||
#
|
#
|
||||||
def add_converter(var_name, const, name = nil, &converter)
|
def add_converter(var_name, const, name = nil, &converter)
|
||||||
if name.nil? # custom converter
|
if name.nil? # custom converter
|
||||||
instance_variable_get("@#{var_name}") << converter
|
instance_variable_get(var_name) << converter
|
||||||
else # named converter
|
else # named converter
|
||||||
combo = const[name]
|
combo = const[name]
|
||||||
case combo
|
case combo
|
||||||
@ -2185,7 +2186,7 @@ class CSV
|
|||||||
add_converter(var_name, const, converter_name)
|
add_converter(var_name, const, converter_name)
|
||||||
end
|
end
|
||||||
else # individual named converter
|
else # individual named converter
|
||||||
instance_variable_get("@#{var_name}") << combo
|
instance_variable_get(var_name) << combo
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -2265,7 +2266,7 @@ class CSV
|
|||||||
class << row
|
class << row
|
||||||
attr_reader :unconverted_fields
|
attr_reader :unconverted_fields
|
||||||
end
|
end
|
||||||
row.instance_eval { @unconverted_fields = fields }
|
row.instance_variable_set(:@unconverted_fields, fields)
|
||||||
row
|
row
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user