Spec-Zone.ru › Ruby 3

класс 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 не является объектом, преобразуемым в целое число.

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; вызывает блок с каждым столбцом как массивом из 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>
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–2020 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

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