класс CSV::Table
CSV::Table
Экземпляр CSV::Table представляет данные CSV. (см. класс CSV).
Экземпляр может содержать:
-
Строки: каждая — объект Table::Row.
-
Заголовки: имена столбцов.
Методы экземпляра
CSV::Table имеет три группы методов экземпляра:
-
Свои внутренние методы экземпляра.
-
Методы, включенные модулем
Enumerable. -
Методы, делегированные классу
Array.:
Создание экземпляра CSV::Table
Обычно новый экземпляр CSV::Table создается путем парсинга источника CSV с использованием заголовков:
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 влияет на поведение некоторых его методов экземпляра:
Режим строк
Переключить таблицу в режим строк с помощью метода by_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>
Указать одну строку по целочисленному индексу:
# 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>]]
Режим столбцов
Переключить таблицу в режим столбцов с помощью метода by_col!:
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"]
Смешанный режим
В смешанном режиме можно ссылаться на строки или столбцы:
-
Целочисленный индекс ссылается на строку.
-
Индекс диапазона ссылается на несколько строк.
-
Строковый индекс ссылается на столбец.
Переключить таблицу в смешанный режим с помощью метода 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"]
Атрибуты
Текущий режим доступа для индексации и итерации.
Внутренний формат данных, используемый для сравнения на равенство.
Публичные методы класса
# 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 Возвращает новый объект 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 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 Если 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 965 def ==(other) return @table == other.table if other.is_a? CSV::Table @table == other end
Возвращает true, если каждая строка self == соответствует соответствующей строке other_table, в противном случае 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 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 Возвращает данные из таблицы; не изменяет таблицу.
- Получение строки по её целочисленному индексу
-
Формат:
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">
Возвращает nil если n слишком велико или слишком мало:
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-й столбец таблицы, если такой столбец существует; в противном случае массив из
nilполей длинойself.size.
Возвращает 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"]
Возвращает массив из nil полей, если n слишком велико или слишком мало:
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 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 Размещает данные в таблице.
-
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 242 def by_col self.class.new(@table.dup).by_col! 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 257 def by_col! @mode = :col self 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 280 def by_col_or_row self.class.new(@table.dup).by_col_or_row! 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 295 def by_col_or_row! @mode = :col_or_row self 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 318 def by_row self.class.new(@table.dup).by_row! 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 333 def by_row! @mode = :row self 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 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 Если режим доступа :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 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 Удаляет строки или столбцы, для которых блок возвращает истинное значение; возвращает 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; вызывает блок с каждым столбцом как массив из двух элементов, содержащий заголовок и массив полей столбца:
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 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 Извлекает вложенное значение, указанное последовательностью объектов index или header, вызывая dig на каждом шаге, возвращая nil, если любой промежуточный шаг nil.
# 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 Вызывает блок с каждой строкой или столбцом; возвращает 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, вызывает блок с каждым столбцом как массив из двух элементов, содержащий заголовок и массив полей столбца:
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 360
def headers
if @table.empty?
@headers.dup
else
@table.first.headers
end
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 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 Возвращает строку в формате 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 788
def push(*rows)
rows.each { |row| self << row }
self # for chaining
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 978
def to_a
array = [headers]
@table.each do |row|
array.push(row.fields) unless row.header_row?
end
array
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 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 Возвращает таблицу как строку 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 (см. {Параметр 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 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 Если режим доступа :row или :col_or_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"]]
Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.