Spec-Zone.ru › Ruby 3.1

класс CSV::Table

Родитель:
Объект
Включенные модули:
Enumerable

A CSV::Table — это двумерная структура данных для представления CSV документов. Таблицы позволяют работать с данными по строкам или столбцам, манипулировать данными и даже преобразовывать результаты обратно в CSV, если необходимо.

Все таблицы, возвращаемые CSV, будут построены из этого класса, если обработка заголовков включена.

Атрибуты

mode[R]

Текущий режим доступа для индексации и итерации.

table[R]

Внутренний формат данных, используемый для сравнения на равенство.

Открытые методы класса

new(array_of_rows, headers: nil) Показать исходный код
# File lib/csv/table.rb, line 31
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 может быть задан как Array заголовков. Если заголовки не заданы, они извлекаются из объектов CSV::Row. В противном случае, метод headers() вернёт заголовки, заданные в аргументе headers.

Объект CSV::Table поддерживает следующие методы Array через делегирование:

  • empty?()

  • length()

  • size()

Методы Публичного Обращения к Экземпляру

table << row_or_array → self Показать исходный код
# File lib/csv/table.rb, line 370
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>
==(other) Показать исходный код
# File lib/csv/table.rb, line 563
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
table[n] → row Показать исходный код
table[range] → array_of_rows
table[header] → array_of_fields
# File lib/csv/table.rb, line 232
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 — целое неотрицательное число, возвращает +n+-ю строку таблицы, если эта строка существует, и если режим доступа — :row или :col_or_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[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 не является объектом, преобразуемым к типу Integer.

table.by_row! # => #<CSV::Table mode:row row_count:4>
# Raises TypeError (no implicit conversion of String into Integer):
table['Name']

Выражение table[range], где range — объект Range, возвращает строки из таблицы, начиная со строки range.first, если эти строки существуют, и если режим доступа — :row или :col_or_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>
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.first до конца:

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[header], где header — строка, возвращает значения столбцов (массив строк) если столбец существует и если режим доступа — :col или :col_or_row:

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]
[]=(index_or_header, value) Показать исходный код
# File lib/csv/table.rb, line 257
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

В режиме по умолчанию (смешанном) этот метод назначает строки для доступа по индексу и столбцы для доступа по заголовкам. Вы можете принудительно установить ассоциацию по индексу, сначала вызвав by_col!() или by_row!().

Строки могут быть заданы как массив значений (который унаследует заголовки таблицы) или как объект CSV::Row.

Столбцы могут быть заданы как одно значение, которое копируется в каждую строку столбца, или как массив значений. Массивы значений назначаются строкам сверху вниз в порядке строк. Избыточные значения игнорируются, и если в массиве значений нет значения для каждой строки, дополнительные строки получат значение nil.

Назначение существующему столбцу или строке перезаписывает данные. Назначение новым столбцам создаёт их в правом конце таблицы.

by_col() Показать исходный код
# File lib/csv/table.rb, line 66
def by_col
  self.class.new(@table.dup).by_col!
end

Возвращает дубликат объекта таблицы в режиме столбцов. Это удобно для цепочки вызовов без изменения режима таблицы, но помните, что этот метод может потреблять значительное количество памяти для больших наборов данных.

Этот метод возвращает дублированную таблицу для цепочки вызовов. Однако не цепляйте деструктивные методы (например, []=()) таким образом, так как вы работаете с дубликатом.

by_col!() Показать исходный код
# File lib/csv/table.rb, line 76
def by_col!
  @mode = :col

  self
end

Переключает режим этой таблицы на режим столбцов. Все вызовы методов индексирования и итерирования будут работать со столбцами, пока режим не будет изменён снова.

Этот метод возвращает таблицу и безопасен для цепочки вызовов.

by_col_or_row() Показать исходный код
# File lib/csv/table.rb, line 91
def by_col_or_row
  self.class.new(@table.dup).by_col_or_row!
end

Возвращает дубликат объекта таблицы в смешанном режиме. Это удобно для цепочки вызовов без изменения режима таблицы, но помните, что этот метод может потреблять значительное количество памяти для больших наборов данных.

Этот метод возвращает дублированную таблицу для цепочки вызовов. Однако не цепляйте деструктивные методы (например, []=()) таким образом, так как вы работаете с дубликатом.

by_col_or_row!() Показать исходный код
# File lib/csv/table.rb, line 103
def by_col_or_row!
  @mode = :col_or_row

  self
end

Переключает режим этой таблицы на смешанный режим. Все вызовы методов индексирования и итерирования будут использовать стандартную интеллектуальную систему индексирования, пока режим не будет изменён снова. В смешанном режиме индекс предполагается как ссылка на строку, а всё остальное — как доступ к столбцу по заголовку.

Этот метод возвращает таблицу и безопасен для цепочки вызовов.

by_row() Показать исходный код
# File lib/csv/table.rb, line 118
def by_row
  self.class.new(@table.dup).by_row!
end

Возвращает дубликат объекта таблицы в режиме строк. Это удобно для цепочки вызовов без изменения режима таблицы, но помните, что этот метод может потреблять значительное количество памяти для больших наборов данных.

Этот метод возвращает дублированную таблицу для цепочки вызовов. Однако не цепляйте деструктивные методы (например, []=()) таким образом, так как вы работаете с дубликатом.

by_row!() Показать исходный код
# File lib/csv/table.rb, line 128
def by_row!
  @mode = :row

  self
end

Переключает режим этой таблицы на режим строк. Все вызовы методов индексирования и итерирования будут работать со строками, пока режим не будет изменён снова.

Этот метод возвращает таблицу и безопасен для цепочки вызовов.

delete(*indexes) → deleted_values Показать исходный код
delete(*headers) → deleted_values
# File lib/csv/table.rb, line 442
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"]]
delete_if() { |header, self| ... } Показать исходный код
# File lib/csv/table.rb, line 492
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
    deleted = []
    headers.each do |header|
      deleted << 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>
dig(index_or_header, *index_or_headers) Показать исходный код
# File lib/csv/table.rb, line 602
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.

each() { |header, self| ... } Показать исходный код
# File lib/csv/table.rb, line 533
def each(&block)
  return enum_for(__method__) { @mode == :col ? headers.size : size } unless block_given?

  if @mode == :col
    headers.each { |header| yield([header, self[header]]) }
  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"]]

Возвращает новый Enumerator, если блок не указан:

table.each # => #<Enumerator: #<CSV::Table mode:col row_count:4>:each>
headers() Показать исходный код
# File lib/csv/table.rb, line 139
def headers
  if @table.empty?
    @headers.dup
  else
    @table.first.headers
  end
end

Возвращает заголовки для первой строки этой таблицы (предполагается, что они соответствуют всем другим строкам). Заголовки Array, переданные в CSV::Table.new, возвращаются для пустых таблиц.

inspect() Показать исходный код
# File lib/csv/table.rb, line 617
def inspect
  "#<#{self.class} mode:#{@mode} row_count:#{to_a.size}>".encode("US-ASCII")
end

Показывает режим и размер этой таблицы в US-ASCII String.

push(*rows_or_arrays) → self Показать исходный код
# File lib/csv/table.rb, line 396
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>]
to_a() Показать исходный код
# File lib/csv/table.rb, line 572
def to_a
  array = [headers]
  @table.each do |row|
    array.push(row.fields) unless row.header_row?
  end

  array
end

Возвращает таблицу как Array массивов. Заголовки будут первой строкой, затем последуют все строки данных.

to_csv(write_headers: true, **options) Показать исходный код
# File lib/csv/table.rb, line 588
def to_csv(write_headers: true, **options)
  array = write_headers ? [headers.to_csv(**options)] : []
  @table.each do |row|
    array.push(row.fields.to_csv(**options)) unless row.header_row?
  end

  array.join("")
end

Возвращает таблицу как полный CSV String. Заголовки будут перечислены первыми, затем все строки данных.

Этот метод предполагает, что вы хотите Table.headers(), если вы явно не передадите :write_headers => false.

Также алиас: to_s
to_s(write_headers: true, **options)
Псевдоним для: to_csv
values_at(*indexes) → array_of_rows Показать исходный код
values_at(*headers) → array_of_columns_data
# File lib/csv/table.rb, line 342
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, и каждый аргумент — целое число или диапазон, возвращает строки. В противном случае возвращает данные столбцов.

В любом случае, возвращаемые значения упорядочены в соответствии с аргументами. Аргументы могут повторяться.

Возвращает строки как массив объектов 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"]]

Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API