Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/AnonR/anonr.TX.../opt/alt/ruby27/share/ruby/csv
File: table.rb
# frozen_string_literal: true
[0] Fix | Delete
[1] Fix | Delete
require "forwardable"
[2] Fix | Delete
[3] Fix | Delete
class CSV
[4] Fix | Delete
#
[5] Fix | Delete
# A CSV::Table is a two-dimensional data structure for representing CSV
[6] Fix | Delete
# documents. Tables allow you to work with the data by row or column,
[7] Fix | Delete
# manipulate the data, and even convert the results back to CSV, if needed.
[8] Fix | Delete
#
[9] Fix | Delete
# All tables returned by CSV will be constructed from this class, if header
[10] Fix | Delete
# row processing is activated.
[11] Fix | Delete
#
[12] Fix | Delete
class Table
[13] Fix | Delete
#
[14] Fix | Delete
# Constructs a new CSV::Table from +array_of_rows+, which are expected
[15] Fix | Delete
# to be CSV::Row objects. All rows are assumed to have the same headers.
[16] Fix | Delete
#
[17] Fix | Delete
# The optional +headers+ parameter can be set to Array of headers.
[18] Fix | Delete
# If headers aren't set, headers are fetched from CSV::Row objects.
[19] Fix | Delete
# Otherwise, headers() method will return headers being set in
[20] Fix | Delete
# headers argument.
[21] Fix | Delete
#
[22] Fix | Delete
# A CSV::Table object supports the following Array methods through
[23] Fix | Delete
# delegation:
[24] Fix | Delete
#
[25] Fix | Delete
# * empty?()
[26] Fix | Delete
# * length()
[27] Fix | Delete
# * size()
[28] Fix | Delete
#
[29] Fix | Delete
def initialize(array_of_rows, headers: nil)
[30] Fix | Delete
@table = array_of_rows
[31] Fix | Delete
@headers = headers
[32] Fix | Delete
unless @headers
[33] Fix | Delete
if @table.empty?
[34] Fix | Delete
@headers = []
[35] Fix | Delete
else
[36] Fix | Delete
@headers = @table.first.headers
[37] Fix | Delete
end
[38] Fix | Delete
end
[39] Fix | Delete
[40] Fix | Delete
@mode = :col_or_row
[41] Fix | Delete
end
[42] Fix | Delete
[43] Fix | Delete
# The current access mode for indexing and iteration.
[44] Fix | Delete
attr_reader :mode
[45] Fix | Delete
[46] Fix | Delete
# Internal data format used to compare equality.
[47] Fix | Delete
attr_reader :table
[48] Fix | Delete
protected :table
[49] Fix | Delete
[50] Fix | Delete
### Array Delegation ###
[51] Fix | Delete
[52] Fix | Delete
extend Forwardable
[53] Fix | Delete
def_delegators :@table, :empty?, :length, :size
[54] Fix | Delete
[55] Fix | Delete
#
[56] Fix | Delete
# Returns a duplicate table object, in column mode. This is handy for
[57] Fix | Delete
# chaining in a single call without changing the table mode, but be aware
[58] Fix | Delete
# that this method can consume a fair amount of memory for bigger data sets.
[59] Fix | Delete
#
[60] Fix | Delete
# This method returns the duplicate table for chaining. Don't chain
[61] Fix | Delete
# destructive methods (like []=()) this way though, since you are working
[62] Fix | Delete
# with a duplicate.
[63] Fix | Delete
#
[64] Fix | Delete
def by_col
[65] Fix | Delete
self.class.new(@table.dup).by_col!
[66] Fix | Delete
end
[67] Fix | Delete
[68] Fix | Delete
#
[69] Fix | Delete
# Switches the mode of this table to column mode. All calls to indexing and
[70] Fix | Delete
# iteration methods will work with columns until the mode is changed again.
[71] Fix | Delete
#
[72] Fix | Delete
# This method returns the table and is safe to chain.
[73] Fix | Delete
#
[74] Fix | Delete
def by_col!
[75] Fix | Delete
@mode = :col
[76] Fix | Delete
[77] Fix | Delete
self
[78] Fix | Delete
end
[79] Fix | Delete
[80] Fix | Delete
#
[81] Fix | Delete
# Returns a duplicate table object, in mixed mode. This is handy for
[82] Fix | Delete
# chaining in a single call without changing the table mode, but be aware
[83] Fix | Delete
# that this method can consume a fair amount of memory for bigger data sets.
[84] Fix | Delete
#
[85] Fix | Delete
# This method returns the duplicate table for chaining. Don't chain
[86] Fix | Delete
# destructive methods (like []=()) this way though, since you are working
[87] Fix | Delete
# with a duplicate.
[88] Fix | Delete
#
[89] Fix | Delete
def by_col_or_row
[90] Fix | Delete
self.class.new(@table.dup).by_col_or_row!
[91] Fix | Delete
end
[92] Fix | Delete
[93] Fix | Delete
#
[94] Fix | Delete
# Switches the mode of this table to mixed mode. All calls to indexing and
[95] Fix | Delete
# iteration methods will use the default intelligent indexing system until
[96] Fix | Delete
# the mode is changed again. In mixed mode an index is assumed to be a row
[97] Fix | Delete
# reference while anything else is assumed to be column access by headers.
[98] Fix | Delete
#
[99] Fix | Delete
# This method returns the table and is safe to chain.
[100] Fix | Delete
#
[101] Fix | Delete
def by_col_or_row!
[102] Fix | Delete
@mode = :col_or_row
[103] Fix | Delete
[104] Fix | Delete
self
[105] Fix | Delete
end
[106] Fix | Delete
[107] Fix | Delete
#
[108] Fix | Delete
# Returns a duplicate table object, in row mode. This is handy for chaining
[109] Fix | Delete
# in a single call without changing the table mode, but be aware that this
[110] Fix | Delete
# method can consume a fair amount of memory for bigger data sets.
[111] Fix | Delete
#
[112] Fix | Delete
# This method returns the duplicate table for chaining. Don't chain
[113] Fix | Delete
# destructive methods (like []=()) this way though, since you are working
[114] Fix | Delete
# with a duplicate.
[115] Fix | Delete
#
[116] Fix | Delete
def by_row
[117] Fix | Delete
self.class.new(@table.dup).by_row!
[118] Fix | Delete
end
[119] Fix | Delete
[120] Fix | Delete
#
[121] Fix | Delete
# Switches the mode of this table to row mode. All calls to indexing and
[122] Fix | Delete
# iteration methods will work with rows until the mode is changed again.
[123] Fix | Delete
#
[124] Fix | Delete
# This method returns the table and is safe to chain.
[125] Fix | Delete
#
[126] Fix | Delete
def by_row!
[127] Fix | Delete
@mode = :row
[128] Fix | Delete
[129] Fix | Delete
self
[130] Fix | Delete
end
[131] Fix | Delete
[132] Fix | Delete
#
[133] Fix | Delete
# Returns the headers for the first row of this table (assumed to match all
[134] Fix | Delete
# other rows). The headers Array passed to CSV::Table.new is returned for
[135] Fix | Delete
# empty tables.
[136] Fix | Delete
#
[137] Fix | Delete
def headers
[138] Fix | Delete
if @table.empty?
[139] Fix | Delete
@headers.dup
[140] Fix | Delete
else
[141] Fix | Delete
@table.first.headers
[142] Fix | Delete
end
[143] Fix | Delete
end
[144] Fix | Delete
[145] Fix | Delete
#
[146] Fix | Delete
# In the default mixed mode, this method returns rows for index access and
[147] Fix | Delete
# columns for header access. You can force the index association by first
[148] Fix | Delete
# calling by_col!() or by_row!().
[149] Fix | Delete
#
[150] Fix | Delete
# Columns are returned as an Array of values. Altering that Array has no
[151] Fix | Delete
# effect on the table.
[152] Fix | Delete
#
[153] Fix | Delete
def [](index_or_header)
[154] Fix | Delete
if @mode == :row or # by index
[155] Fix | Delete
(@mode == :col_or_row and (index_or_header.is_a?(Integer) or index_or_header.is_a?(Range)))
[156] Fix | Delete
@table[index_or_header]
[157] Fix | Delete
else # by header
[158] Fix | Delete
@table.map { |row| row[index_or_header] }
[159] Fix | Delete
end
[160] Fix | Delete
end
[161] Fix | Delete
[162] Fix | Delete
#
[163] Fix | Delete
# In the default mixed mode, this method assigns rows for index access and
[164] Fix | Delete
# columns for header access. You can force the index association by first
[165] Fix | Delete
# calling by_col!() or by_row!().
[166] Fix | Delete
#
[167] Fix | Delete
# Rows may be set to an Array of values (which will inherit the table's
[168] Fix | Delete
# headers()) or a CSV::Row.
[169] Fix | Delete
#
[170] Fix | Delete
# Columns may be set to a single value, which is copied to each row of the
[171] Fix | Delete
# column, or an Array of values. Arrays of values are assigned to rows top
[172] Fix | Delete
# to bottom in row major order. Excess values are ignored and if the Array
[173] Fix | Delete
# does not have a value for each row the extra rows will receive a +nil+.
[174] Fix | Delete
#
[175] Fix | Delete
# Assigning to an existing column or row clobbers the data. Assigning to
[176] Fix | Delete
# new columns creates them at the right end of the table.
[177] Fix | Delete
#
[178] Fix | Delete
def []=(index_or_header, value)
[179] Fix | Delete
if @mode == :row or # by index
[180] Fix | Delete
(@mode == :col_or_row and index_or_header.is_a? Integer)
[181] Fix | Delete
if value.is_a? Array
[182] Fix | Delete
@table[index_or_header] = Row.new(headers, value)
[183] Fix | Delete
else
[184] Fix | Delete
@table[index_or_header] = value
[185] Fix | Delete
end
[186] Fix | Delete
else # set column
[187] Fix | Delete
unless index_or_header.is_a? Integer
[188] Fix | Delete
index = @headers.index(index_or_header) || @headers.size
[189] Fix | Delete
@headers[index] = index_or_header
[190] Fix | Delete
end
[191] Fix | Delete
if value.is_a? Array # multiple values
[192] Fix | Delete
@table.each_with_index do |row, i|
[193] Fix | Delete
if row.header_row?
[194] Fix | Delete
row[index_or_header] = index_or_header
[195] Fix | Delete
else
[196] Fix | Delete
row[index_or_header] = value[i]
[197] Fix | Delete
end
[198] Fix | Delete
end
[199] Fix | Delete
else # repeated value
[200] Fix | Delete
@table.each do |row|
[201] Fix | Delete
if row.header_row?
[202] Fix | Delete
row[index_or_header] = index_or_header
[203] Fix | Delete
else
[204] Fix | Delete
row[index_or_header] = value
[205] Fix | Delete
end
[206] Fix | Delete
end
[207] Fix | Delete
end
[208] Fix | Delete
end
[209] Fix | Delete
end
[210] Fix | Delete
[211] Fix | Delete
#
[212] Fix | Delete
# The mixed mode default is to treat a list of indices as row access,
[213] Fix | Delete
# returning the rows indicated. Anything else is considered columnar
[214] Fix | Delete
# access. For columnar access, the return set has an Array for each row
[215] Fix | Delete
# with the values indicated by the headers in each Array. You can force
[216] Fix | Delete
# column or row mode using by_col!() or by_row!().
[217] Fix | Delete
#
[218] Fix | Delete
# You cannot mix column and row access.
[219] Fix | Delete
#
[220] Fix | Delete
def values_at(*indices_or_headers)
[221] Fix | Delete
if @mode == :row or # by indices
[222] Fix | Delete
( @mode == :col_or_row and indices_or_headers.all? do |index|
[223] Fix | Delete
index.is_a?(Integer) or
[224] Fix | Delete
( index.is_a?(Range) and
[225] Fix | Delete
index.first.is_a?(Integer) and
[226] Fix | Delete
index.last.is_a?(Integer) )
[227] Fix | Delete
end )
[228] Fix | Delete
@table.values_at(*indices_or_headers)
[229] Fix | Delete
else # by headers
[230] Fix | Delete
@table.map { |row| row.values_at(*indices_or_headers) }
[231] Fix | Delete
end
[232] Fix | Delete
end
[233] Fix | Delete
[234] Fix | Delete
#
[235] Fix | Delete
# Adds a new row to the bottom end of this table. You can provide an Array,
[236] Fix | Delete
# which will be converted to a CSV::Row (inheriting the table's headers()),
[237] Fix | Delete
# or a CSV::Row.
[238] Fix | Delete
#
[239] Fix | Delete
# This method returns the table for chaining.
[240] Fix | Delete
#
[241] Fix | Delete
def <<(row_or_array)
[242] Fix | Delete
if row_or_array.is_a? Array # append Array
[243] Fix | Delete
@table << Row.new(headers, row_or_array)
[244] Fix | Delete
else # append Row
[245] Fix | Delete
@table << row_or_array
[246] Fix | Delete
end
[247] Fix | Delete
[248] Fix | Delete
self # for chaining
[249] Fix | Delete
end
[250] Fix | Delete
[251] Fix | Delete
#
[252] Fix | Delete
# A shortcut for appending multiple rows. Equivalent to:
[253] Fix | Delete
#
[254] Fix | Delete
# rows.each { |row| self << row }
[255] Fix | Delete
#
[256] Fix | Delete
# This method returns the table for chaining.
[257] Fix | Delete
#
[258] Fix | Delete
def push(*rows)
[259] Fix | Delete
rows.each { |row| self << row }
[260] Fix | Delete
[261] Fix | Delete
self # for chaining
[262] Fix | Delete
end
[263] Fix | Delete
[264] Fix | Delete
#
[265] Fix | Delete
# Removes and returns the indicated columns or rows. In the default mixed
[266] Fix | Delete
# mode indices refer to rows and everything else is assumed to be a column
[267] Fix | Delete
# headers. Use by_col!() or by_row!() to force the lookup.
[268] Fix | Delete
#
[269] Fix | Delete
def delete(*indexes_or_headers)
[270] Fix | Delete
if indexes_or_headers.empty?
[271] Fix | Delete
raise ArgumentError, "wrong number of arguments (given 0, expected 1+)"
[272] Fix | Delete
end
[273] Fix | Delete
deleted_values = indexes_or_headers.map do |index_or_header|
[274] Fix | Delete
if @mode == :row or # by index
[275] Fix | Delete
(@mode == :col_or_row and index_or_header.is_a? Integer)
[276] Fix | Delete
@table.delete_at(index_or_header)
[277] Fix | Delete
else # by header
[278] Fix | Delete
if index_or_header.is_a? Integer
[279] Fix | Delete
@headers.delete_at(index_or_header)
[280] Fix | Delete
else
[281] Fix | Delete
@headers.delete(index_or_header)
[282] Fix | Delete
end
[283] Fix | Delete
@table.map { |row| row.delete(index_or_header).last }
[284] Fix | Delete
end
[285] Fix | Delete
end
[286] Fix | Delete
if indexes_or_headers.size == 1
[287] Fix | Delete
deleted_values[0]
[288] Fix | Delete
else
[289] Fix | Delete
deleted_values
[290] Fix | Delete
end
[291] Fix | Delete
end
[292] Fix | Delete
[293] Fix | Delete
#
[294] Fix | Delete
# Removes any column or row for which the block returns +true+. In the
[295] Fix | Delete
# default mixed mode or row mode, iteration is the standard row major
[296] Fix | Delete
# walking of rows. In column mode, iteration will +yield+ two element
[297] Fix | Delete
# tuples containing the column name and an Array of values for that column.
[298] Fix | Delete
#
[299] Fix | Delete
# This method returns the table for chaining.
[300] Fix | Delete
#
[301] Fix | Delete
# If no block is given, an Enumerator is returned.
[302] Fix | Delete
#
[303] Fix | Delete
def delete_if(&block)
[304] Fix | Delete
return enum_for(__method__) { @mode == :row or @mode == :col_or_row ? size : headers.size } unless block_given?
[305] Fix | Delete
[306] Fix | Delete
if @mode == :row or @mode == :col_or_row # by index
[307] Fix | Delete
@table.delete_if(&block)
[308] Fix | Delete
else # by header
[309] Fix | Delete
deleted = []
[310] Fix | Delete
headers.each do |header|
[311] Fix | Delete
deleted << delete(header) if yield([header, self[header]])
[312] Fix | Delete
end
[313] Fix | Delete
end
[314] Fix | Delete
[315] Fix | Delete
self # for chaining
[316] Fix | Delete
end
[317] Fix | Delete
[318] Fix | Delete
include Enumerable
[319] Fix | Delete
[320] Fix | Delete
#
[321] Fix | Delete
# In the default mixed mode or row mode, iteration is the standard row major
[322] Fix | Delete
# walking of rows. In column mode, iteration will +yield+ two element
[323] Fix | Delete
# tuples containing the column name and an Array of values for that column.
[324] Fix | Delete
#
[325] Fix | Delete
# This method returns the table for chaining.
[326] Fix | Delete
#
[327] Fix | Delete
# If no block is given, an Enumerator is returned.
[328] Fix | Delete
#
[329] Fix | Delete
def each(&block)
[330] Fix | Delete
return enum_for(__method__) { @mode == :col ? headers.size : size } unless block_given?
[331] Fix | Delete
[332] Fix | Delete
if @mode == :col
[333] Fix | Delete
headers.each { |header| yield([header, self[header]]) }
[334] Fix | Delete
else
[335] Fix | Delete
@table.each(&block)
[336] Fix | Delete
end
[337] Fix | Delete
[338] Fix | Delete
self # for chaining
[339] Fix | Delete
end
[340] Fix | Delete
[341] Fix | Delete
# Returns +true+ if all rows of this table ==() +other+'s rows.
[342] Fix | Delete
def ==(other)
[343] Fix | Delete
return @table == other.table if other.is_a? CSV::Table
[344] Fix | Delete
@table == other
[345] Fix | Delete
end
[346] Fix | Delete
[347] Fix | Delete
#
[348] Fix | Delete
# Returns the table as an Array of Arrays. Headers will be the first row,
[349] Fix | Delete
# then all of the field rows will follow.
[350] Fix | Delete
#
[351] Fix | Delete
def to_a
[352] Fix | Delete
array = [headers]
[353] Fix | Delete
@table.each do |row|
[354] Fix | Delete
array.push(row.fields) unless row.header_row?
[355] Fix | Delete
end
[356] Fix | Delete
[357] Fix | Delete
array
[358] Fix | Delete
end
[359] Fix | Delete
[360] Fix | Delete
#
[361] Fix | Delete
# Returns the table as a complete CSV String. Headers will be listed first,
[362] Fix | Delete
# then all of the field rows.
[363] Fix | Delete
#
[364] Fix | Delete
# This method assumes you want the Table.headers(), unless you explicitly
[365] Fix | Delete
# pass <tt>:write_headers => false</tt>.
[366] Fix | Delete
#
[367] Fix | Delete
def to_csv(write_headers: true, **options)
[368] Fix | Delete
array = write_headers ? [headers.to_csv(**options)] : []
[369] Fix | Delete
@table.each do |row|
[370] Fix | Delete
array.push(row.fields.to_csv(**options)) unless row.header_row?
[371] Fix | Delete
end
[372] Fix | Delete
[373] Fix | Delete
array.join("")
[374] Fix | Delete
end
[375] Fix | Delete
alias_method :to_s, :to_csv
[376] Fix | Delete
[377] Fix | Delete
#
[378] Fix | Delete
# Extracts the nested value specified by the sequence of +index+ or +header+ objects by calling dig at each step,
[379] Fix | Delete
# returning nil if any intermediate step is nil.
[380] Fix | Delete
#
[381] Fix | Delete
def dig(index_or_header, *index_or_headers)
[382] Fix | Delete
value = self[index_or_header]
[383] Fix | Delete
if value.nil?
[384] Fix | Delete
nil
[385] Fix | Delete
elsif index_or_headers.empty?
[386] Fix | Delete
value
[387] Fix | Delete
else
[388] Fix | Delete
unless value.respond_to?(:dig)
[389] Fix | Delete
raise TypeError, "#{value.class} does not have \#dig method"
[390] Fix | Delete
end
[391] Fix | Delete
value.dig(*index_or_headers)
[392] Fix | Delete
end
[393] Fix | Delete
end
[394] Fix | Delete
[395] Fix | Delete
# Shows the mode and size of this table in a US-ASCII String.
[396] Fix | Delete
def inspect
[397] Fix | Delete
"#<#{self.class} mode:#{@mode} row_count:#{to_a.size}>".encode("US-ASCII")
[398] Fix | Delete
end
[399] Fix | Delete
end
[400] Fix | Delete
end
[401] Fix | Delete
[402] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function