class CSV::Row
CSV::Row¶ ↑
CSV::Row 实例表示 CSV 表格中的一行。(请参阅 class CSV)。
该实例可能具有:
-
字段:每个字段都是一个对象,不一定是字符串。
-
标题:每个标题用作键,也不一定是字符串。
实例方法¶ ↑
CSV::Row 有三组实例方法:
-
自身内部定义的实例方法。
-
模块 Enumerable 包含的方法。
-
委托给
Array
类的方法。-
Array#empty?
-
Array#length
-
Array#size
-
创建 CSV::Row 实例¶ ↑
通常,新的 CSV::Row 实例是通过解析带有标题的 CSV 源创建的。
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) table.each {|row| p row }
输出
#<CSV::Row "Name":"foo" "Value":"0"> #<CSV::Row "Name":"bar" "Value":"1"> #<CSV::Row "Name":"baz" "Value":"2">
您也可以直接创建行。请参阅 ::new
。
标题¶ ↑
像 CSV::Table 一样,CSV::Row 也有标题。
通过解析 CSV 源创建的 CSV::Row 会从表格中继承其标题。
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) row = table.first row.headers # => ["Name", "Value"]
您也可以使用标题创建新行;像哈希中的键一样,标题不必是字符串。
row = CSV::Row.new([:name, :value], ['foo', 0]) row.headers # => [:name, :value]
即使添加到具有标题的表格中,新行也会保留其标题。
table << row # => #<CSV::Table mode:col_or_row row_count:5> row.headers # => [:name, :value] row[:name] # => "foo" row['Name'] # => nil
访问字段¶ ↑
您可以使用整数索引(数组样式)或标题(哈希样式)访问 CSV::Row 中的字段。
使用方法 []
获取字段
row = CSV::Row.new(['Name', 'Value'], ['foo', 0]) row[1] # => 0 row['Value'] # => 0
使用方法 []=
设置字段
row = CSV::Row.new(['Name', 'Value'], ['foo', 0]) row # => #<CSV::Row "Name":"foo" "Value":0> row[0] = 'bar' row['Value'] = 1 row # => #<CSV::Row "Name":"bar" "Value":1>
属性
用于比较相等性的内部数据格式。
公共类方法
返回从参数 headers
和 fields
构造的新 CSV::Row 实例;两者都应为数组;请注意,字段不必是字符串。
row = CSV::Row.new(['Name', 'Value'], ['foo', 0]) row # => #<CSV::Row "Name":"foo" "Value":0>
如果数组长度不同,则较短的数组将用 nil
填充。
row = CSV::Row.new(['Name', 'Value', 'Date', 'Size'], ['foo', 0]) row # => #<CSV::Row "Name":"foo" "Value":0 "Date":nil "Size":nil>
每个 CSV::Row 对象要么是字段行,要么是标题行;默认情况下,新行是字段行;对于上面创建的行。
row.field_row? # => true row.header_row? # => false
如果可选参数 header_row
给定为 true
,则创建的行是标题行。
row = CSV::Row.new(['Name', 'Value'], ['foo', 0], header_row = true) row # => #<CSV::Row "Name":"foo" "Value":0> row.field_row? # => false row.header_row? # => true
# File csv-3.3.2/lib/csv/row.rb, line 105 def initialize(headers, fields, header_row = false) @header_row = header_row headers.each { |h| h.freeze if h.is_a? String } # handle extra headers or fields @row = if headers.size >= fields.size headers.zip(fields) else fields.zip(headers).each(&:reverse!) end end
公共实例方法
向 self
添加一个字段;返回 self
。
如果参数是 2 元素数组 [header, value]
,则会添加一个具有给定 header
和 value
的字段。
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row << ['NAME', 'Bat'] row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" "NAME":"Bat">
如果参数是哈希,则每个 key-value
对将作为具有标题 key
和值 value
的字段添加。
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row << {NAME: 'Bat', name: 'Bam'} row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" NAME:"Bat" name:"Bam">
否则,给定的 value
将作为没有标题的字段添加。
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row << 'Bag' row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" nil:"Bag">
# File csv-3.3.2/lib/csv/row.rb, line 389 def <<(arg) if arg.is_a?(Array) and arg.size == 2 # appending a header and name @row << arg elsif arg.is_a?(Hash) # append header and name pairs arg.each { |pair| @row << pair } else # append field value @row << [nil, arg] end self # for chaining end
如果 other
是 /CSV::Row,并且具有与 self
相同顺序的相同字段(标题和值),则返回 true
;否则返回 false
。
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] other_row = table[0] row == other_row # => true other_row = table[1] row == other_row # => false
# File csv-3.3.2/lib/csv/row.rb, line 633 def ==(other) return @row == other.row if other.is_a? CSV::Row @row == other end
为给定的 index
或 header
分配字段值;返回 value
。
按整数索引分配字段值
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) row = table[0] row[0] = 'Bat' row[1] = 3 row # => #<CSV::Row "Name":"Bat" "Value":3>
如果 index
为负数,则从最后一列向后计数。
row[-1] = 4 row[-2] = 'Bam' row # => #<CSV::Row "Name":"Bam" "Value":4>
如果正数 index
不在该行中,则使用 nil:nil
扩展该行。
row[4] = 5 row # => #<CSV::Row "Name":"bad" "Value":4 nil:nil nil:nil nil:5>
如果负数 index
太小(离零太远),则引发 IndexError。
按标题分配字段值(第一个找到的)
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row['Name'] = 'Bat' row # => #<CSV::Row "Name":"Bat" "Name":"Bar" "Name":"Baz">
按标题分配字段值,忽略 offset
个前导字段
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row['Name', 2] = 4 row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":4>
通过(新)标题追加新字段
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) row = table[0] row['New'] = 6 row# => #<CSV::Row "Name":"foo" "Value":"0" "New":6>
# File csv-3.3.2/lib/csv/row.rb, line 339 def []=(*args) value = args.pop if args.first.is_a? Integer if @row[args.first].nil? # extending past the end with index @row[args.first] = [nil, value] @row.map! { |pair| pair.nil? ? [nil, nil] : pair } else # normal index assignment @row[args.first][1] = value end else index = index(*args) if index.nil? # appending a field self << [args.first, value] else # normal header assignment @row[index][1] = value end end end
返回适用于模式匹配的新数组,其中包含行的值。
# File csv-3.3.2/lib/csv/row.rb, line 682 def deconstruct fields end
返回适用于模式匹配的新哈希,其中仅包含指定为参数的键。
# File csv-3.3.2/lib/csv/row.rb, line 667 def deconstruct_keys(keys) if keys.nil? to_h else keys.to_h { |key| [key, self[key]] } end end
从 self
中删除指定的字段;如果字段存在,则返回 2 元素数组 [header, value]
。
如果给定了整数参数 index
,则删除并返回偏移量为 index
的字段,如果该字段不存在,则返回 nil
。
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row.delete(1) # => ["Name", "Bar"] row.delete(50) # => nil
否则,如果给定了单个参数 header
,则删除并返回第一个找到的具有给定标题的字段,如果该字段不存在,则返回新的空数组。
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row.delete('Name') # => ["Name", "Foo"] row.delete('NAME') # => []
如果给定了参数 header
和整数参数 offset
,则删除并返回第一个找到的具有给定标题的字段,其 index
至少与 offset
一样大。
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row.delete('Name', 1) # => ["Name", "Bar"] row.delete('NAME', 1) # => []
# File csv-3.3.2/lib/csv/row.rb, line 451 def delete(header_or_index, minimum_index = 0) if header_or_index.is_a? Integer # by index @row.delete_at(header_or_index) elsif i = index(header_or_index, minimum_index) # by header @row.delete_at(i) else [ ] end end
删除块所选的 self
中的字段;返回 self
。
删除块返回真值时的每个字段。
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row.delete_if {|header, value| value.start_with?('B') } # => true row # => #<CSV::Row "Name":"Foo"> row.delete_if {|header, value| header.start_with?('B') } # => false
如果没有给出块,则返回新的枚举器。
row.delete_if # => #<Enumerator: #<CSV::Row "Name":"Foo">:delete_if>
# File csv-3.3.2/lib/csv/row.rb, line 476 def delete_if(&block) return enum_for(__method__) { size } unless block_given? @row.delete_if(&block) self # for chaining end
查找并返回嵌套对象中由 index_or_header
和 specifiers
指定的对象。
嵌套对象可能是各种类的实例。请参阅 Dig 方法。
示例
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) row = table[0] row.dig(1) # => "0" row.dig('Value') # => "0" row.dig(5) # => nil
# File csv-3.3.2/lib/csv/row.rb, line 715 def dig(index_or_header, *indexes) value = field(index_or_header) if value.nil? nil elsif indexes.empty? value else unless value.respond_to?(:dig) raise TypeError, "#{value.class} does not have \#dig method" end value.dig(*indexes) end end
使用每个标题-值对调用块;返回 self
。
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row.each {|header, value| p [header, value] }
输出
["Name", "Foo"] ["Name", "Bar"] ["Name", "Baz"]
如果没有给出块,则返回新的枚举器。
row.each # => #<Enumerator: #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz">:each>
# File csv-3.3.2/lib/csv/row.rb, line 610 def each(&block) return enum_for(__method__) { size } unless block_given? @row.each(&block) self # for chaining end
返回由 header
指定的字段值。
使用单个参数 header
,返回该标题的字段值(第一个找到的)。
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row.fetch('Name') # => "Foo"
如果标题不存在,则引发异常 KeyError
。
如果给定了参数 header
和 default
,则如果标题存在,则返回该标题的字段值(第一个找到的),否则返回 default
。
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row.fetch('Name', '') # => "Foo" row.fetch(:nosuch, '') # => ""
如果给定了参数 header
和一个块,则如果标题存在,则返回该标题的字段值(第一个找到的);否则调用该块并返回其返回值。
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row.fetch('Name') {|header| fail 'Cannot happen' } # => "Foo" row.fetch(:nosuch) {|header| "Header '#{header} not found'" } # => "Header 'nosuch not found'"
# File csv-3.3.2/lib/csv/row.rb, line 258 def fetch(header, *varargs) raise ArgumentError, "Too many arguments" if varargs.length > 1 pair = @row.assoc(header) if pair pair.last else if block_given? yield header elsif varargs.empty? raise KeyError, "key not found: #{header}" else varargs.first end end end
返回给定 index
或 header
的字段值。
按整数索引获取字段值
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) row = table[0] row.field(0) # => "foo" row.field(1) # => "bar"
如果 index
为负数,则从最后一列向后计数。
row.field(-1) # => "0" row.field(-2) # => "foo"
如果 index
超出范围,则返回 nil
。
row.field(2) # => nil row.field(-3) # => nil
按标题获取字段值(第一个找到的)
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row.field('Name') # => "Foo"
按标题获取字段值,忽略 offset
个前导字段
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row.field('Name', 2) # => "Baz"
如果标题不存在,则返回 nil
。
# File csv-3.3.2/lib/csv/row.rb, line 203 def field(header_or_index, minimum_index = 0) # locate the pair finder = (header_or_index.is_a?(Integer) || header_or_index.is_a?(Range)) ? :[] : :assoc pair = @row[minimum_index..-1].public_send(finder, header_or_index) # return the field if we have a pair if pair.nil? nil else header_or_index.is_a?(Range) ? pair.map(&:last) : pair.last end end
如果 value
是此行中的一个字段,则返回 true
,否则返回 false
。
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row.field?('Bar') # => true row.field?('BAR') # => false
# File csv-3.3.2/lib/csv/row.rb, line 589 def field?(data) fields.include? data end
如果这是一个字段行,则返回 true
,否则返回 false
。
# File csv-3.3.2/lib/csv/row.rb, line 148 def field_row? not header_row? end
根据给定的 specifiers
返回字段值,它可以是以下任何混合形式:
-
整数索引。
-
整数索引的范围。
-
包含标题和偏移量的 2 元素数组。
-
标题。
-
标题的范围。
对于上面前四种情况中的一种 specifier
,返回 self.field(specifier)
的结果;请参阅 field
。
尽管可以有任意数量的 specifiers
,但此处的示例将一次说明一个。
当 specifier 是一个整数 index
时,返回 self.field(index)
。
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row.fields(1) # => ["Bar"]
当 specifier 是一个整数范围 range
时,返回 self.field(range)
。
row.fields(1..2) # => ["Bar", "Baz"]
当 specifier 是一个 2 元素数组 array
时,返回 self.field(array)
。
row.fields('Name', 1) # => ["Foo", "Bar"]
当 specifier 是一个标题 header
时,返回 self.field(header)
。
row.fields('Name') # => ["Foo"]
当 specifier 是一个标题范围 range
时,从 range.start
和 range.end
的索引中形成一个新的范围 new_range
,并返回 self.field(new_range)
。
source = "Name,NAME,name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row.fields('Name'..'NAME') # => ["Foo", "Bar"]
如果没有给出参数,则返回所有字段。
row.fields # => ["Foo", "Bar", "Baz"]
# File csv-3.3.2/lib/csv/row.rb, line 530 def fields(*headers_and_or_indices) if headers_and_or_indices.empty? # return all fields--no arguments @row.map(&:last) else # or work like values_at() all = [] 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(h_or_i.begin) index_end = h_or_i.end.is_a?(Integer) ? h_or_i.end : index(h_or_i.end) new_range = h_or_i.exclude_end? ? (index_begin...index_end) : (index_begin..index_end) all.concat(fields.values_at(new_range)) else all << field(*Array(h_or_i)) end end return all end end
如果存在具有给定 header
的字段,则返回 true
,否则返回 false
。
# File csv-3.3.2/lib/csv/row.rb, line 279 def has_key?(header) !!@row.assoc(header) end
如果这是一个标题行,则返回 true
,否则返回 false
。
# File csv-3.3.2/lib/csv/row.rb, line 140 def header_row? @header_row end
返回此行的标题
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) row = table.first row.headers # => ["Name", "Value"]
# File csv-3.3.2/lib/csv/row.rb, line 160 def headers @row.map(&:first) end
返回给定标题的索引(如果存在);否则返回 nil
。
使用单个参数 header
,返回第一个找到的具有给定 header
的字段的索引。
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row.index('Name') # => 0 row.index('NAME') # => nil
使用参数 header
和 offset
,返回第一个找到的具有给定 header
的字段的索引,但忽略前 offset
个字段。
row.index('Name', 1) # => 1 row.index('Name', 3) # => nil
# File csv-3.3.2/lib/csv/row.rb, line 573 def index(header, minimum_index = 0) # find the pair index = headers[minimum_index..-1].index(header) # return the index at the right offset, if we found one index.nil? ? nil : index + minimum_index end
调用超类方法。
# File csv-3.3.2/lib/csv/row.rb, line 130 def initialize_copy(other) super_return_value = super @row = @row.collect(&:dup) super_return_value end
返回一个显示
-
CSV::Row 类的 ASCII 兼容字符串。
-
头-值对。
示例
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) row = table[0] row.inspect # => "#<CSV::Row \"Name\":\"foo\" \"Value\":\"0\">"
# File csv-3.3.2/lib/csv/row.rb, line 740 def inspect str = ["#<", self.class.to_s] each do |header, field| str << " " << (header.is_a?(Symbol) ? header.to_s : header.inspect) << ":" << field.inspect end str << ">" begin str.join('') rescue # any encoding error str.map do |s| e = Encoding::Converter.asciicompat_encoding(s.encoding) e ? s.encode(e) : s.force_encoding("ASCII-8BIT") end.join('') end end
将给定的每个 values
追加到 self
作为字段;返回 self
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row.push('Bat', 'Bam') row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" nil:"Bat" nil:"Bam">
# File csv-3.3.2/lib/csv/row.rb, line 410 def push(*args) args.each { |arg| self << arg } self # for chaining end
将行作为 CSV String
返回。不包含标题
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) row = table[0] row.to_csv # => "foo,0\n"
# File csv-3.3.2/lib/csv/row.rb, line 694 def to_csv(**options) fields.to_csv(**options) end
返回一个新的哈希,该哈希通过将 self
中的每个头-值对作为哈希中的键-值对添加而形成。
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" table = CSV.parse(source, headers: true) row = table[0] row.to_h # => {"Name"=>"foo", "Value"=>"0"}
保留标题顺序,但重复的标题将被忽略
source = "Name,Name,Name\nFoo,Bar,Baz\n" table = CSV.parse(source, headers: true) row = table[0] row.to_h # => {"Name"=>"Foo"}
# File csv-3.3.2/lib/csv/row.rb, line 653 def to_h hash = {} each do |key, _value| hash[key] = self[key] unless hash.key?(key) end hash end