类 CSV::Table
CSV::Table¶ ↑
CSV::Table 实例表示 CSV 数据。(参见 类 CSV)。
实例可能具有
-
行:每个都是 Table::Row 对象。
-
标题:列的名称。
实例方法¶ ↑
CSV::Table 有三组实例方法
-
它自己内部定义的实例方法。
-
模块
Enumerable
包含的方法。 -
委托给类
Array
的方法。
创建 CSV::Table 实例¶ ↑
通常,通过使用标题解析 CSV 源来创建新的 CSV::Table 实例
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.class # => CSV::Table
你还可以直接创建一个实例。请参阅 ::new
。
标题¶ ↑
如果一个表有标题,则标题用作数据列的标签。每个标题用作其列的标签。
CSV::Table 对象的标题存储为字符串数组。
通常,标题在 CSV 源的第一行中定义
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.headers # => ["Name", "Value"]
如果没有定义标题,则数组为空
table = CSV::Table.new([]) table.headers # => []
访问模式¶ ↑
CSV::Table 提供了三种访问表数据的方式
-
行模式。
-
列模式。
-
混合模式(新表的默认模式)。
CSV::Table 实例的访问模式影响其某些实例方法的行为
行模式¶ ↑
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.by_row! # => #<CSV::Table mode:row row_count:4>
通过整数索引指定单行
# Get a row. table[1] # => #<CSV::Row "Name":"bar" "Value":"1"> # Set a row, then get it. table[1] = CSV::Row.new(['Name', 'Value'], ['bam', 3]) table[1] # => #<CSV::Row "Name":"bam" "Value":3>
通过范围指定一系列行
# Get rows. table[1..2] # => [#<CSV::Row "Name":"bam" "Value":3>, #<CSV::Row "Name":"baz" "Value":"2">] # Set rows, then get them. table[1..2] = [ CSV::Row.new(['Name', 'Value'], ['bat', 4]), CSV::Row.new(['Name', 'Value'], ['bad', 5]), ] table[1..2] # => [["Name", #<CSV::Row "Name":"bat" "Value":4>], ["Value", #<CSV::Row "Name":"bad" "Value":5>]]
列模式¶ ↑
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.by_col! # => #<CSV::Table mode:col row_count:4>
通过整数索引指定列
# Get a column. table[0] # Set a column, then get it. table[0] = ['FOO', 'BAR', 'BAZ'] table[0] # => ["FOO", "BAR", "BAZ"]
通过字符串标题指定列
# Get a column. table['Name'] # => ["FOO", "BAR", "BAZ"] # Set a column, then get it. table['Name'] = ['Foo', 'Bar', 'Baz'] table['Name'] # => ["Foo", "Bar", "Baz"]
混合模式¶ ↑
在混合模式中,您可以引用行或列
-
整数索引引用行。
-
范围索引引用多行。
-
字符串索引引用列。
Set
使用方法 by_col_or_row!
将表格设置为混合模式
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
通过整数索引指定单行
# Get a row. table[1] # => #<CSV::Row "Name":"bar" "Value":"1"> # Set a row, then get it. table[1] = CSV::Row.new(['Name', 'Value'], ['bam', 3]) table[1] # => #<CSV::Row "Name":"bam" "Value":3>
通过范围指定一系列行
# Get rows. table[1..2] # => [#<CSV::Row "Name":"bam" "Value":3>, #<CSV::Row "Name":"baz" "Value":"2">] # Set rows, then get them. table[1] = CSV::Row.new(['Name', 'Value'], ['bat', 4]) table[2] = CSV::Row.new(['Name', 'Value'], ['bad', 5]) table[1..2] # => [["Name", #<CSV::Row "Name":"bat" "Value":4>], ["Value", #<CSV::Row "Name":"bad" "Value":5>]]
通过字符串标题指定列
# Get a column. table['Name'] # => ["foo", "bat", "bad"] # Set a column, then get it. table['Name'] = ['Foo', 'Bar', 'Baz'] table['Name'] # => ["Foo", "Bar", "Baz"]
属性
当前访问模式,用于索引和迭代。
用于比较相等性的内部数据格式。
公共类方法
返回新的 CSV::Table 对象。
-
参数
array_of_rows
必须是CSV::Row
对象的数组。 -
如果给定参数
headers
,它可以是字符串数组。
创建一个空的 CSV::Table 对象
table = CSV::Table.new([]) table # => #<CSV::Table mode:col_or_row row_count:1>
创建一个非空的 CSV::Table 对象
rows = [ CSV::Row.new([], []), CSV::Row.new([], []), CSV::Row.new([], []), ] table = CSV::Table.new(rows) table # => #<CSV::Table mode:col_or_row row_count:4>
如果参数 headers
是字符串数组,则这些字符串将成为表格的标题
table = CSV::Table.new([], headers: ['Name', 'Age']) table.headers # => ["Name", "Age"]
如果未给定参数 headers
并且表格有行,则标题将取自第一行
rows = [ CSV::Row.new(['Foo', 'Bar'], []), CSV::Row.new(['foo', 'bar'], []), CSV::Row.new(['FOO', 'BAR'], []), ] table = CSV::Table.new(rows) table.headers # => ["Foo", "Bar"]
如果未给定参数 headers
并且表格为空(没有行),则标题也为空
table = CSV::Table.new([]) table.headers # => []
如果参数 array_of_rows
不是数组对象,则引发异常
# Raises NoMethodError (undefined method `first' for :foo:Symbol): CSV::Table.new(:foo)
如果 array_of_rows
的元素不是 CSV::Table 对象,则引发异常
# Raises NoMethodError (undefined method `headers' for :foo:Symbol): CSV::Table.new([:foo])
# File lib/csv/table.rb, line 199 def initialize(array_of_rows, headers: nil) @table = array_of_rows @headers = headers unless @headers if @table.empty? @headers = [] else @headers = @table.first.headers end end @mode = :col_or_row end
公共实例方法
如果 row_or_array
是 CSV::Row 对象,则将其追加到表格中
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table << CSV::Row.new(table.headers, ['bat', 3]) table[3] # => #<CSV::Row "Name":"bat" "Value":3>
如果 row_or_array
是数组,则使用它创建一个新的 CSV::Row 对象,然后将其追加到表格中
table << ['bam', 4] table[4] # => #<CSV::Row "Name":"bam" "Value":4>
# File lib/csv/table.rb, line 762 def <<(row_or_array) if row_or_array.is_a? Array # append Array @table << Row.new(headers, row_or_array) else # append Row @table << row_or_array end self # for chaining end
如果 self
的每一行都 ==
other_table
的对应行,则返回 true
,否则返回 false
。
访问模式不会影响结果。
相等表格
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) other_table = CSV.parse(source, headers: true) table == other_table # => true
行数不同
other_table.delete(2) table == other_table # => false
最后一行不同
other_table << ['bat', 3] table == other_table # => false
# File lib/csv/table.rb, line 965 def ==(other) return @table == other.table if other.is_a? CSV::Table @table == other end
从表中返回数据;不修改表。
- 按整数索引获取行
-
格式:
table[n]
,n
为整数。 -
访问模式:
:row
或:col_or_row
。 -
返回值:表的第 n 行(如果该行存在);否则为
nil
。
如果该行存在,则返回表的第 n 行
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.by_row! # => #<CSV::Table mode:row row_count:4> table[1] # => #<CSV::Row "Name":"bar" "Value":"1"> table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4> table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
如果 n
为负数,则从最后一行开始向后计数
table[-1] # => #<CSV::Row "Name":"baz" "Value":"2">
如果 n
过大或过小,则返回 nil
table[4] # => nil table[-4] # => nil
如果访问模式为 :row
且 n
不是整数,则引发异常
table.by_row! # => #<CSV::Table mode:row row_count:4> # Raises TypeError (no implicit conversion of String into Integer): table['Name']
- 按整数索引获取列
-
格式:
table[n]
,n
为整数。 -
访问模式:
:col
。 -
返回值:表的第 n 列(如果该列存在);否则为长度为
self.size
的nil
字段数组。
如果该列存在,则返回表的第 n 列
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.by_col! # => #<CSV::Table mode:col row_count:4> table[1] # => ["0", "1", "2"]
如果 n
为负数,则从最后一列开始向后计数
table[-2] # => ["foo", "bar", "baz"]
如果 n
过大或过小,则返回 nil
字段数组
table[4] # => [nil, nil, nil] table[-4] # => [nil, nil, nil]
- 按范围获取行
-
格式:
table[range]
,range
为范围对象。 -
访问模式:
:row
或:col_or_row
。 -
返回值:从行
range.start
开始的表行(如果这些行存在)。
从行 range.first
开始返回表行(如果这些行存在)
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.by_row! # => #<CSV::Table mode:row row_count:4> rows = table[1..2] # => #<CSV::Row "Name":"bar" "Value":"1"> rows # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">] table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4> rows = table[1..2] # => #<CSV::Row "Name":"bar" "Value":"1"> rows # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
如果行太少,则从 range.start
到末尾返回所有行
rows = table[1..50] # => #<CSV::Row "Name":"bar" "Value":"1"> rows # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
特殊情况:如果 range.start == table.size
,则返回一个空数组
table[table.size..50] # => []
如果 range.end
为负数,则从末尾计算结束索引
rows = table[0..-1] rows # => [#<CSV::Row "Name":"foo" "Value":"0">, #<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
如果 range.start
为负数,则从末尾计算开始索引
rows = table[-1..2] rows # => [#<CSV::Row "Name":"baz" "Value":"2">]
如果 range.start
大于 table.size
,则返回 nil
table[4..4] # => nil
- 按范围获取列
-
格式:
table[range]
,range
为范围对象。 -
访问模式:
:col
。 -
返回值:从列
range.start
开始的表列数据(如果这些列存在)。
如果列存在,则返回表中的列值;这些值按行排列
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.by_col! table[0..1] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
特殊情况:如果 range.start == headers.size
,则返回一个由空数组组成的数组(大小:table.size
)
table[table.headers.size..50] # => [[], [], []]
如果 range.end
为负数,则从末尾计算结束索引
table[0..-1] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
如果 range.start
为负数,则从末尾计算开始索引
table[-2..2] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
如果 range.start
大于 table.size
,则返回一个由 nil
值组成的数组
table[4..4] # => [nil, nil, nil]
- 按其字符串标题获取列
-
形式:
table[header]
,header
是字符串标题。 -
访问模式:
:col
或:col_or_row
-
返回值:如果该
header
存在,则返回表中的列数据。
如果列存在,则返回表中的列值
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.by_col! # => #<CSV::Table mode:col row_count:4> table['Name'] # => ["foo", "bar", "baz"] table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4> col = table['Name'] col # => ["foo", "bar", "baz"]
修改返回的列值不会修改表
col[0] = 'bat' col # => ["bat", "bar", "baz"] table['Name'] # => ["foo", "bar", "baz"]
如果没有该列,则返回一个由 nil
值组成的数组
table['Nosuch'] # => [nil, nil, nil]
# File lib/csv/table.rb, line 514 def [](index_or_header) if @mode == :row or # by index (@mode == :col_or_row and (index_or_header.is_a?(Integer) or index_or_header.is_a?(Range))) @table[index_or_header] else # by header @table.map { |row| row[index_or_header] } end end
将数据放入表中。
Set
按其整数索引设置行
-
形式:
table[n] = row
,n
为整数,row
为 CSV::Row 实例或字段数组。 -
访问模式:
:row
或:col_or_row
。 -
返回值:
row
。
如果行存在,则替换它
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) new_row = CSV::Row.new(['Name', 'Value'], ['bat', 3]) table.by_row! # => #<CSV::Table mode:row row_count:4> return_value = table[0] = new_row return_value.equal?(new_row) # => true # Returned the row table[0].to_h # => {"Name"=>"bat", "Value"=>3}
访问模式为 :col_or_row
table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4> table[0] = CSV::Row.new(['Name', 'Value'], ['bam', 4]) table[0].to_h # => {"Name"=>"bam", "Value"=>4}
使用数组而不是 CSV::Row,从表中继承标题
array = ['bad', 5] return_value = table[0] = array return_value.equal?(array) # => true # Returned the array table[0].to_h # => {"Name"=>"bad", "Value"=>5}
如果行不存在,则通过添加行来扩展表:根据需要分配具有 nil
的行
table.size # => 3 table[5] = ['bag', 6] table.size # => 6 table[3] # => nil table[4]# => nil table[5].to_h # => {"Name"=>"bag", "Value"=>6}
请注意,nil
行实际上是 nil
,而不是 nil
字段的行。
Set
按其整数索引设置列
-
形式:
table[n] = array_of_fields
,n
为整数,array_of_fields
为字符串字段数组。 -
访问模式:
:col
。 -
返回值:
array_of_fields
。
如果列存在,则替换它
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) new_col = [3, 4, 5] table.by_col! # => #<CSV::Table mode:col row_count:4> return_value = table[1] = new_col return_value.equal?(new_col) # => true # Returned the column table[1] # => [3, 4, 5] # The rows, as revised: table.by_row! # => #<CSV::Table mode:row row_count:4> table[0].to_h # => {"Name"=>"foo", "Value"=>3} table[1].to_h # => {"Name"=>"bar", "Value"=>4} table[2].to_h # => {"Name"=>"baz", "Value"=>5} table.by_col! # => #<CSV::Table mode:col row_count:4>
如果值太少,则用 nil
值填充
table[1] = [0] table[1] # => [0, nil, nil]
如果值太多,则忽略多余的值
table[1] = [0, 1, 2, 3, 4] table[1] # => [0, 1, 2]
如果给定单个值,则用该值替换列中的所有字段
table[1] = 'bat' table[1] # => ["bat", "bat", "bat"]
Set
按其字符串标题设置列
-
形式:
table[header] = field_or_array_of_fields
,header
为字符串标题,field_or_array_of_fields
为字段值或字符串字段数组。 -
访问模式:
:col
或:col_or_row
。 -
返回值:
field_or_array_of_fields
。
如果列存在,则替换它
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) new_col = [3, 4, 5] table.by_col! # => #<CSV::Table mode:col row_count:4> return_value = table['Value'] = new_col return_value.equal?(new_col) # => true # Returned the column table['Value'] # => [3, 4, 5] # The rows, as revised: table.by_row! # => #<CSV::Table mode:row row_count:4> table[0].to_h # => {"Name"=>"foo", "Value"=>3} table[1].to_h # => {"Name"=>"bar", "Value"=>4} table[2].to_h # => {"Name"=>"baz", "Value"=>5} table.by_col! # => #<CSV::Table mode:col row_count:4>
如果值太少,则用 nil
值填充
table['Value'] = [0] table['Value'] # => [0, nil, nil]
如果值太多,则忽略多余的值
table['Value'] = [0, 1, 2, 3, 4] table['Value'] # => [0, 1, 2]
如果列不存在,则通过添加列来扩展表
table['Note'] = ['x', 'y', 'z'] table['Note'] # => ["x", "y", "z"] # The rows, as revised: table.by_row! table[0].to_h # => {"Name"=>"foo", "Value"=>0, "Note"=>"x"} table[1].to_h # => {"Name"=>"bar", "Value"=>1, "Note"=>"y"} table[2].to_h # => {"Name"=>"baz", "Value"=>2, "Note"=>"z"} table.by_col!
如果给定单个值,则用该值替换列中的所有字段
table['Value'] = 'bat' table['Value'] # => ["bat", "bat", "bat"]
# File lib/csv/table.rb, line 649 def []=(index_or_header, value) if @mode == :row or # by index (@mode == :col_or_row and index_or_header.is_a? Integer) if value.is_a? Array @table[index_or_header] = Row.new(headers, value) else @table[index_or_header] = value end else # set column unless index_or_header.is_a? Integer index = @headers.index(index_or_header) || @headers.size @headers[index] = index_or_header end if value.is_a? Array # multiple values @table.each_with_index do |row, i| if row.header_row? row[index_or_header] = index_or_header else row[index_or_header] = value[i] end end else # repeated value @table.each do |row| if row.header_row? row[index_or_header] = index_or_header else row[index_or_header] = value end end end end end
返回 self
的副本,采用列模式(请参阅 列模式)
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.mode # => :col_or_row dup_table = table.by_col dup_table.mode # => :col dup_table.equal?(table) # => false # It's a dup
这可以用来链接方法调用而不更改模式(但也会影响性能和内存使用情况)
dup_table.by_col['Name']
还要注意,对副本表进行的更改不会影响原表。
# File lib/csv/table.rb, line 242 def by_col self.class.new(@table.dup).by_col! end
将 self
的模式设置为列模式(请参阅 列模式);返回 self
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.mode # => :col_or_row table1 = table.by_col! table.mode # => :col table1.equal?(table) # => true # Returned self
# File lib/csv/table.rb, line 257 def by_col! @mode = :col self end
以混合模式返回 self
的副本(请参阅 混合模式)
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true).by_col! table.mode # => :col dup_table = table.by_col_or_row dup_table.mode # => :col_or_row dup_table.equal?(table) # => false # It's a dup
这可以用来链接方法调用而不更改模式(但也会影响性能和内存使用情况)
dup_table.by_col_or_row['Name']
还要注意,对副本表进行的更改不会影响原表。
# File lib/csv/table.rb, line 280 def by_col_or_row self.class.new(@table.dup).by_col_or_row! end
将 self
的模式设置为混合模式(请参阅 混合模式);返回 self
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true).by_col! table.mode # => :col table1 = table.by_col_or_row! table.mode # => :col_or_row table1.equal?(table) # => true # Returned self
# File lib/csv/table.rb, line 295 def by_col_or_row! @mode = :col_or_row self end
以行模式返回 self
的副本(请参阅 行模式)
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.mode # => :col_or_row dup_table = table.by_row dup_table.mode # => :row dup_table.equal?(table) # => false # It's a dup
这可以用来链接方法调用而不更改模式(但也会影响性能和内存使用情况)
dup_table.by_row[1]
还要注意,对副本表进行的更改不会影响原表。
# File lib/csv/table.rb, line 318 def by_row self.class.new(@table.dup).by_row! end
将 self
的模式设置为行模式(请参阅 行模式);返回 self
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.mode # => :col_or_row table1 = table.by_row! table.mode # => :row table1.equal?(table) # => true # Returned self
# File lib/csv/table.rb, line 333 def by_row! @mode = :row self end
如果访问模式为 :row
或 :col_or_row
,并且每个参数都是整数或范围,则返回已删除的行。否则,返回已删除的列数据。
在任何一种情况下,返回的值都按参数指定的顺序排列。参数可以重复。
将行作为 CSV::Row 对象的数组返回。
一个索引
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) deleted_values = table.delete(0) deleted_values # => [#<CSV::Row "Name":"foo" "Value":"0">]
两个索引
table = CSV.parse(source, headers: true) deleted_values = table.delete(2, 0) deleted_values # => [#<CSV::Row "Name":"baz" "Value":"2">, #<CSV::Row "Name":"foo" "Value":"0">]
将列数据作为列数组返回。
一个标题
table = CSV.parse(source, headers: true) deleted_values = table.delete('Name') deleted_values # => ["foo", "bar", "baz"]
两个标题
table = CSV.parse(source, headers: true) deleted_values = table.delete('Value', 'Name') deleted_values # => [["0", "1", "2"], ["foo", "bar", "baz"]]
# File lib/csv/table.rb, line 834 def delete(*indexes_or_headers) if indexes_or_headers.empty? raise ArgumentError, "wrong number of arguments (given 0, expected 1+)" end deleted_values = indexes_or_headers.map do |index_or_header| if @mode == :row or # by index (@mode == :col_or_row and index_or_header.is_a? Integer) @table.delete_at(index_or_header) else # by header if index_or_header.is_a? Integer @headers.delete_at(index_or_header) else @headers.delete(index_or_header) end @table.map { |row| row.delete(index_or_header).last } end end if indexes_or_headers.size == 1 deleted_values[0] else deleted_values end end
删除块返回真值的行或列;返回 self
。
在访问模式为 :row
或 :col_or_row
时删除行;使用每个 CSV::Row 对象调用块
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.by_row! # => #<CSV::Table mode:row row_count:4> table.size # => 3 table.delete_if {|row| row['Name'].start_with?('b') } table.size # => 1
当访问模式为 :col
时,移除列;使用每个列作为包含标题和列字段数组的 2 元素数组,调用块
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.by_col! # => #<CSV::Table mode:col row_count:4> table.headers.size # => 2 table.delete_if {|column_data| column_data[1].include?('2') } table.headers.size # => 1
如果没有提供块,则返回一个新的枚举器
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.delete_if # => #<Enumerator: #<CSV::Table mode:col_or_row row_count:4>:delete_if>
# File lib/csv/table.rb, line 887 def delete_if(&block) return enum_for(__method__) { @mode == :row or @mode == :col_or_row ? size : headers.size } unless block_given? if @mode == :row or @mode == :col_or_row # by index @table.delete_if(&block) else # by header headers.each do |header| delete(header) if yield([header, self[header]]) end end self # for chaining end
通过在每一步调用 dig 提取由 index
或 header
对象序列指定嵌套值,如果任何中间步骤为 nil,则返回 nil。
# File lib/csv/table.rb, line 1021 def dig(index_or_header, *index_or_headers) value = self[index_or_header] if value.nil? nil elsif index_or_headers.empty? value else unless value.respond_to?(:dig) raise TypeError, "#{value.class} does not have \#dig method" end value.dig(*index_or_headers) end end
使用每个行或列调用块;返回 self
。
当访问模式为 :row
或 :col_or_row
时,使用每个 CSV::Row 对象调用块
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.by_row! # => #<CSV::Table mode:row row_count:4> table.each {|row| p row }
输出
#<CSV::Row "Name":"foo" "Value":"0"> #<CSV::Row "Name":"bar" "Value":"1"> #<CSV::Row "Name":"baz" "Value":"2">
当访问模式为 :col
时,使用每个列作为包含标题和列字段数组的 2 元素数组,调用块
table.by_col! # => #<CSV::Table mode:col row_count:4> table.each {|column_data| p column_data }
输出
["Name", ["foo", "bar", "baz"]] ["Value", ["0", "1", "2"]]
如果没有提供块,则返回一个新的枚举器
table.each # => #<Enumerator: #<CSV::Table mode:col row_count:4>:each>
# File lib/csv/table.rb, line 930 def each(&block) return enum_for(__method__) { @mode == :col ? headers.size : size } unless block_given? if @mode == :col headers.each.with_index do |header, i| yield([header, @table.map {|row| row[header, i]}]) end else @table.each(&block) end self # for chaining end
返回一个包含表格的字符串标题的新数组。
如果表格不为空,则返回第一行的标题
rows = [ CSV::Row.new(['Foo', 'Bar'], []), CSV::Row.new(['FOO', 'BAR'], []), CSV::Row.new(['foo', 'bar'], []), ] table = CSV::Table.new(rows) table.headers # => ["Foo", "Bar"] table.delete(0) table.headers # => ["FOO", "BAR"] table.delete(0) table.headers # => ["foo", "bar"]
如果表格为空,则返回表格本身中标题的副本
table.delete(0) table.headers # => ["Foo", "Bar"]
# File lib/csv/table.rb, line 360 def headers if @table.empty? @headers.dup else @table.first.headers end end
返回显示表格的 US-ASCII
编码字符串
-
类:
CSV::Table
。 -
访问模式:
:row
、:col
或:col_or_row
。 -
大小:
Row
计数,包括标题行。
示例
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.inspect # => "#<CSV::Table mode:col_or_row row_count:4>\nName,Value\nfoo,0\nbar,1\nbaz,2\n"
# File lib/csv/table.rb, line 1048 def inspect inspected = +"#<#{self.class} mode:#{@mode} row_count:#{to_a.size}>" summary = to_csv(limit: 5) inspected << "\n" << summary if summary.encoding.ascii_compatible? inspected end
附加多行的快捷方式。等效于
rows.each {|row| self << row }
每个参数可以是 CSV::Row 对象或数组
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) rows = [ CSV::Row.new(table.headers, ['bat', 3]), ['bam', 4] ] table.push(*rows) table[3..4] # => [#<CSV::Row "Name":"bat" "Value":3>, #<CSV::Row "Name":"bam" "Value":4>]
# File lib/csv/table.rb, line 788 def push(*rows) rows.each { |row| self << row } self # for chaining end
将表格作为数组的数组返回;标题在第一行
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.to_a # => [["Name", "Value"], ["foo", "0"], ["bar", "1"], ["baz", "2"]]
# File lib/csv/table.rb, line 978 def to_a array = [headers] @table.each do |row| array.push(row.fields) unless row.header_row? end array end
将表格作为 CSV 字符串返回。请参阅生成选项。
将选项 write_headers
的默认值设为 true
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.to_csv # => "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
如果选项 write_headers
给定为 false
,则省略标题(参见 {Option write_headers
})
table.to_csv(write_headers: false) # => "foo,0\nbar,1\nbaz,2\n"
如果选项 limit
给定为 2
,则限制行数
table.to_csv(limit: 2) # => "Name,Value\nfoo,0\nbar,1\n"
# File lib/csv/table.rb, line 1004 def to_csv(write_headers: true, limit: nil, **options) array = write_headers ? [headers.to_csv(**options)] : [] limit ||= @table.size limit = @table.size + 1 + limit if limit < 0 limit = 0 if limit < 0 @table.first(limit).each do |row| array.push(row.fields.to_csv(**options)) unless row.header_row? end array.join("") end
如果访问模式为 :row
或 :col_or_row
,且每个参数都是整数或范围,则返回行。否则,返回列数据。
在任何一种情况下,返回的值都按参数指定的顺序排列。参数可以重复。
将行作为 CSV::Row 对象的数组返回。
无参数
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.values_at # => []
一个索引
values = table.values_at(0) values # => [#<CSV::Row "Name":"foo" "Value":"0">]
两个索引
values = table.values_at(2, 0) values # => [#<CSV::Row "Name":"baz" "Value":"2">, #<CSV::Row "Name":"foo" "Value":"0">]
一个范围
values = table.values_at(1..2) values # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
范围和索引
values = table.values_at(0..1, 1..2, 0, 2) pp values
输出
[#<CSV::Row "Name":"foo" "Value":"0">, #<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">, #<CSV::Row "Name":"foo" "Value":"0">, #<CSV::Row "Name":"baz" "Value":"2">]
将列数据作为行数组返回,每个数组都包含该行的指定列数据
values = table.values_at('Name') values # => [["foo"], ["bar"], ["baz"]] values = table.values_at('Value', 'Name') values # => [["0", "foo"], ["1", "bar"], ["2", "baz"]]
# File lib/csv/table.rb, line 734 def values_at(*indices_or_headers) if @mode == :row or # by indices ( @mode == :col_or_row and indices_or_headers.all? do |index| index.is_a?(Integer) or ( index.is_a?(Range) and index.first.is_a?(Integer) and index.last.is_a?(Integer) ) end ) @table.values_at(*indices_or_headers) else # by headers @table.map { |row| row.values_at(*indices_or_headers) } end end