Commit fa85d2c6 by Ivan Lan

feat: 合并一列一值数据 & 分裂赋值还有问题

parent d7156933
...@@ -38,6 +38,10 @@ module TalltyImportExport ...@@ -38,6 +38,10 @@ module TalltyImportExport
def seq def seq
@seq ||= SecureRandom.uuid @seq ||= SecureRandom.uuid
end end
# def living_alone?
# depth == 0 && children.present?
# end
end end
class ExportHeader class ExportHeader
......
...@@ -35,6 +35,7 @@ module TalltyImportExport ...@@ -35,6 +35,7 @@ module TalltyImportExport
index += 1 index += 1
value_seq_to_axios = {} value_seq_to_axios = {}
formats = [] formats = []
association_records.each do |association_record| association_records.each do |association_record|
records = @each_method.present? ? records = @each_method.present? ?
...@@ -42,43 +43,26 @@ module TalltyImportExport ...@@ -42,43 +43,26 @@ module TalltyImportExport
[association_record] [association_record]
records.each do |record| records.each do |record|
lines = TalltyImportExport::ExportPayload.new(record, header: header_obj) do |payload, header| value_living_alone_col_index_to_value_count = {}
payload = TalltyImportExport::ExportPayload.new(record, header: header_obj) do |payload, header|
_data = header[:source] ? _data = header[:source] ?
handle_data(association_record, header, index) : handle_data(association_record, header, index) :
handle_data(payload, header, index) handle_data(payload, header, index)
end.lines end
# lines.each { |x| p x.map { |x| x.try(:value) || '________' } }
# result = []
# lines.transpose.map do |transposed_line|
# line = transposed_line
# while line[0].nil?
# line.shift
# line.push(false)
# end
# line
# end.transpose.each do |line|
# if line.select(&:itself).count > 0
# result << line
# end
# end
# result_uniq = result.uniq do |line|
# line.map { |x| x.try(:value) }
# end#.sort do |a, b|
#a.map { |x| x.try(:value) } <=> b.map { |x| x.try(:value) }
#end
p '----------------------------------------------------------------' # p '----------------------------------------------------------------'
lines.each { |x| p x.map { |x| x.try(:value) || '________' } } # payload.lines.each { |x| p x.map { |x| x.try(:value) || '________' } }
lines.each_with_index do |line, row_index| payload.lines.each_with_index do |line, row_index|
row = [] row = []
line.each_with_index do |value, col_index| line.each_with_index do |value, col_index|
value_living_alone_col_index_to_value_count[col_index] ||= 0
if (TalltyImportExport::ExportPayload::Value === value) if (TalltyImportExport::ExportPayload::Value === value)
row << value.value row << value.value
value_living_alone_col_index_to_value_count[col_index] += 1
unless value_seq_to_axios[value.seq] unless value_seq_to_axios[value.seq]
value_seq_to_axios[value.seq] = [] value_seq_to_axios[value.seq] = []
end end
...@@ -89,12 +73,24 @@ module TalltyImportExport ...@@ -89,12 +73,24 @@ module TalltyImportExport
formats.push(header_obj.flatten_value[col_index].format&.to_sym || (row.is_a?(String) ? :string : nil)) formats.push(header_obj.flatten_value[col_index].format&.to_sym || (row.is_a?(String) ? :string : nil))
end end
sheet.add_row(row, style: title3, height: @row_height, types: formats) sheet.add_row(row, style: title3, height: @row_height, types: formats)
index += 1
formats = [] formats = []
end end
# 合并仅有一个值的一列中所有格子
value_living_alone_col_index_to_value_count.each_pair do |col_index, count|
if count == 1
sheet.merge_cells(
Axlsx::cell_r(col_index, index) + ':' + Axlsx::cell_r(col_index, index + payload.max_matrix_height - 1)
)
end end
end end
index += payload.max_matrix_height
end
end
# 合并相同值
# value_seq_to_axios.values.each do |axios_ary| # value_seq_to_axios.values.each do |axios_ary|
# if axios_ary.count > 1 # if axios_ary.count > 1
# top_right = [axios_ary.map(&:first).min, axios_ary.map(&:last).min] # top_right = [axios_ary.map(&:first).min, axios_ary.map(&:last).min]
...@@ -104,6 +100,8 @@ module TalltyImportExport ...@@ -104,6 +100,8 @@ module TalltyImportExport
# ) # )
# end # end
# end # end
end end
end end
......
require 'matrix' require 'matrix'
class TalltyImportExport::ExportPayload class TalltyImportExport::ExportPayload
attr_reader :value, :context extend ActiveSupport::Autoload
autoload :Value
autoload :CellColumn
autoload :Cell
attr_reader :value, :context, :cell_columns, :max_matrix_height
def initialize(val, header:, &value_handler) def initialize(val, header:, &value_handler)
@value = TalltyImportExport::ExportPayload::Value.new(val) @value = TalltyImportExport::ExportPayload::Value.new(val)
...@@ -10,13 +16,12 @@ class TalltyImportExport::ExportPayload ...@@ -10,13 +16,12 @@ class TalltyImportExport::ExportPayload
@value_handler = value_handler @value_handler = value_handler
@context = { @context = {
header_seq_to_value_seq_to_value: {}, header_seq_to_value_seq_to_value: {},
value_inherited_seq_to_header_seq_to_value: {},
flatten_headers: @flatten_headers, flatten_headers: @flatten_headers,
} }
end end
def lines def lines
cell_columns = @headers.map do |header| @cell_columns = @headers.map do |header|
TalltyImportExport::ExportPayload::CellColumn.new( TalltyImportExport::ExportPayload::CellColumn.new(
header, header,
self.value, self.value,
...@@ -26,208 +31,31 @@ class TalltyImportExport::ExportPayload ...@@ -26,208 +31,31 @@ class TalltyImportExport::ExportPayload
end end
# 分离的,每个初始 header 为一个矩阵 # 分离的,每个初始 header 为一个矩阵
matrixes = cell_columns.map do |cell_column| matrixes = @cell_columns.map do |cell_column|
cell_column.tallest_cell_cluster.map(&:grow_to_line) cell_column.tallest_cell_cluster.map(&:grow_to_line)
end end
# 计算所有矩阵中最高高度,用于填充 # 计算所有矩阵中最高高度,用于填充
max_matrix_height = matrixes.map(&:count).max @max_matrix_height = matrixes.map(&:count).max
# 填充各个矩阵至等高 # 填充各个矩阵至等高
detached_matrixes = matrixes.map do |ragged_col| detached_matrixes = matrixes.map do |ragged_col|
col = ragged_col.uniq col = ragged_col.uniq
while col.count < max_matrix_height while col.count < @max_matrix_height
col.push(col[0].count.times.to_a) col.push(col[0].count.times.to_a)
end end
Matrix[*col] Matrix[*col]
end end
# 合并矩阵
result = detached_matrixes.reduce do |out, matrix| result = detached_matrixes.reduce do |out, matrix|
Matrix.hstack(out, matrix) Matrix.hstack(out, matrix)
end.to_a end.to_a
# .select do |line|
# line.select { |value| TalltyImportExport::ExportPayload::Value === value }.count > 0
# end
# result.map { |x| p x.map { |xx| xx.try(:value)}} # result.map { |x| p x.map { |xx| xx.try(:value)}}
result result
end end
end end
class TalltyImportExport::ExportPayload::Value
attr_reader :value, :seq_chain#, :inherited_seq
def initialize(val, seq_chain=[], inherited_seq: false)
@value = val
@seq_chain = inherited_seq ? seq_chain : [*seq_chain, seq]
end
def seq
@seq ||= SecureRandom.uuid
end
end
# 一个 竖列
class TalltyImportExport::ExportPayload::CellColumn
attr_reader :header, :payload, :context, :cell_clusters, :flatten_cells, :tallest_cell_cluster
def initialize header, value, context, &value_handler
@header = header
@value = value
@context = context
@cell_clusters = []
@value_handler = value_handler
if header.children
@cell_clusters = @value.value[header.key.to_sym].map do |val|
TalltyImportExport::ExportPayload::Cell.new(
@header,
TalltyImportExport::ExportPayload::Value.new(val, @value.seq_chain),
@context,
&@value_handler
)
end
else
@cell_clusters = [
TalltyImportExport::ExportPayload::Cell.new(
@header,
TalltyImportExport::ExportPayload::Value.new(
@value_handler.call(@value.value, @header.as_json.symbolize_keys),
@value.seq_chain,
),
@context,
&@value_handler
)
]
end
@flatten_cells = []
cell_divise
end
def cell_divise
@flatten_cells = @cell_clusters.map do |cell_cluster|
cell_cluster.divise.cell_cluster
end.flatten
depth_to_cells_mapping = @flatten_cells.group_by { |cell| cell.depth }
@tallest_cell_cluster = depth_to_cells_mapping.values.max { |a, b| a.count <=> b.count }
self
end
end
class TalltyImportExport::ExportPayload::Cell
attr_accessor :cell_cluster, :val, :header, :parent_path
# cell_cluster 是表格纵向 集合
# cell_the_same_line 是表格横向 集合
def initialize header, value, context, parent_path=[], &value_handler
@value = value
@header = header
@value_handler = value_handler
# context
@context = context
value.seq_chain.each do |s|
# s = value.seq
unless (@context[:header_seq_to_value_seq_to_value][header.seq])
@context[:header_seq_to_value_seq_to_value][header.seq] = {}
end
@context[:header_seq_to_value_seq_to_value][header.seq][s] = value # NOTE: value 对象
end
# unless (@context[:value_inherited_seq_to_header_seq_to_value][value.inherited_seq])
# @context[:value_inherited_seq_to_header_seq_to_value][value.inherited_seq] = {}
# end
# @context[:value_inherited_seq_to_header_seq_to_value][value.inherited_seq][header.seq] = value # NOTE: value 对象
# parent
@parent_path = parent_path
@cell_cluster = []
end
def seq
@seq ||= SecureRandom.uuid
end
def depth
@parent_path.count
end
def header_chain_seqs
[*@parent_path, self].map { |cell| cell.header.cluster_seqs }.reduce(:concat)
end
def divise
if @header.children.present?
new_cells = @header.children.map do |child_header|
if (child_header.children.present?)
val = @value.value[child_header.key.to_sym]
val.map do |val|
TalltyImportExport::ExportPayload::Cell.new(
child_header,
TalltyImportExport::ExportPayload::Value.new(val, @value.seq_chain, inherited_seq: true),
@context,
[*self.parent_path, self],
&@value_handler
)
end
else
val = @value_handler.call(@value.value, child_header.as_json.symbolize_keys)
TalltyImportExport::ExportPayload::Cell.new(
child_header,
TalltyImportExport::ExportPayload::Value.new(val, @value.seq_chain),
@context,
[*self.parent_path, self],
&@value_handler
)
end
end.flatten
new_cells.each(&:divise)
@cell_cluster.concat(new_cells.map(&:cell_cluster))
else
@cell_cluster = [self]
end
self
end
def grow_to_line
@context[:flatten_headers].
select do |header|
header_chain_seqs.include?(header.seq)
end.
map do |header|
target_value = nil
# if @context[:value_inherited_seq_to_header_seq_to_value][@value.inherited_seq]&.[](header.seq)
# target_value = @context[:value_inherited_seq_to_header_seq_to_value][@value.inherited_seq][header.seq]
# end
@value.seq_chain.uniq.reverse.each do |seq|
next if target_value
# seq = @value.seq
if @context[:header_seq_to_value_seq_to_value][header.seq]&.[](seq)
target_value = @context[:header_seq_to_value_seq_to_value][header.seq][seq]
end
end
# require 'irb'
# if target_value == 'c1_4____'
# binding.irb
# end
# @value.seq_chain.uniq.reverse.each do |seq|
# next if target_value
# if @context[:header_seq_to_value_seq_to_value][seq]&.[](header.seq)
# target_value = @context[:header_seq_to_value_seq_to_value][seq][header.seq]
# end
# end
target_value
end
end
end
class TalltyImportExport::ExportPayload::Cell
attr_accessor :cell_cluster, :value, :header, :parent_path
# cell_cluster 是表格纵向 集合
# cell_the_same_line 是表格横向 集合
def initialize header, value, context, parent_path=[], &value_handler
@value = value
@header = header
@value_handler = value_handler
# context
@context = context
value.seq_chain.each do |s|
unless (@context[:header_seq_to_value_seq_to_value][header.seq])
@context[:header_seq_to_value_seq_to_value][header.seq] = {}
end
@context[:header_seq_to_value_seq_to_value][header.seq][s] = value # NOTE: value 对象
end
# parent
@parent_path = parent_path
@cell_cluster = []
end
def seq
@seq ||= SecureRandom.uuid
end
def depth
@parent_path.count
end
def header_chain_seqs
[*@parent_path, self].map { |cell| cell.header.cluster_seqs }.reduce(:concat)
end
def divise
if @header.children.present?
new_cells = @header.children.map do |child_header|
if (child_header.children.present?)
val = @value.value[child_header.key.to_sym]
order = 0
val.map do |val|
cell = TalltyImportExport::ExportPayload::Cell.new(
child_header,
TalltyImportExport::ExportPayload::Value.new(val, @value.chain, inherited: true),
@context,
[*self.parent_path, self],
&@value_handler
)
order += 1
cell
end
else
val = @value_handler.call(@value.value, child_header.as_json.symbolize_keys)
TalltyImportExport::ExportPayload::Cell.new(
child_header,
TalltyImportExport::ExportPayload::Value.new(val, @value.chain),
@context,
[*self.parent_path, self],
&@value_handler
)
end
end.flatten
new_cells.each(&:divise)
@cell_cluster.concat(new_cells.map(&:cell_cluster))
else
@cell_cluster = [self]
end
self
end
def grow_to_line
@context[:flatten_headers].
select do |header|
header_chain_seqs.include?(header.seq)
end.
map do |header|
target_value = nil
@value.seq_chain.uniq.reverse.each do |seq|
next if target_value
# seq = @value.seq
if @context[:header_seq_to_value_seq_to_value][header.seq]&.[](seq)
target_value = @context[:header_seq_to_value_seq_to_value][header.seq][seq]
end
end
target_value
end
end
end
# 一个 最大的竖列,分子列前的竖列
class TalltyImportExport::ExportPayload::CellColumn
attr_reader :header, :payload, :context, :cell_clusters, :flatten_cells, :tallest_cell_cluster
def initialize header, value, context, &value_handler
@header = header
@value = value
@context = context
@cell_clusters = []
@value_handler = value_handler
if header.children
@cell_clusters = @value.value[header.key.to_sym].map do |val|
TalltyImportExport::ExportPayload::Cell.new(
@header,
TalltyImportExport::ExportPayload::Value.new(val, @value.chain),
@context,
&@value_handler
)
end
else
@cell_clusters = [
TalltyImportExport::ExportPayload::Cell.new(
@header,
TalltyImportExport::ExportPayload::Value.new(
@value_handler.call(@value.value, @header.as_json.symbolize_keys),
@value.chain,
),
@context,
&@value_handler
)
]
end
@flatten_cells = []
cell_divise
end
def cell_divise
divised_cell_clusters = @cell_clusters.map do |cell_cluster|
cell_cluster.divise.cell_cluster
end
@flatten_cells = divised_cell_clusters.flatten
depth_to_cells_mapping = @flatten_cells.group_by { |cell| [cell.depth, cell.header.seq] }
@tallest_cell_cluster = depth_to_cells_mapping.values.max { |a, b| a.count <=> b.count }
self
end
end
class TalltyImportExport::ExportPayload::Value
attr_reader :value, :chain, :seq_chain
def initialize(val, chain=[], inherited: false)
@value = val
@parent_chain = chain
@chain = inherited ? @parent_chain : [*@parent_chain, self]
@seq_chain = @chain.map(&:seq)
end
def seq
@seq ||= SecureRandom.uuid
end
end
...@@ -35,6 +35,7 @@ RSpec.describe TalltyImportExport::Importable do ...@@ -35,6 +35,7 @@ RSpec.describe TalltyImportExport::Importable do
{ e31: 'e31_2_0_', e32: 'e32_2_0_', e33: 'e33_2_0_' }, { e31: 'e31_2_0_', e32: 'e32_2_0_', e33: 'e33_2_0_' },
{ e31: 'e31_2_1_', e32: 'e32_2_1_', e33: 'e33_2_1_' }, { e31: 'e31_2_1_', e32: 'e32_2_1_', e33: 'e33_2_1_' },
{ e31: 'e31_2_2_', e32: 'e32_2_2_', e33: 'e33_2_2_' }, { e31: 'e31_2_2_', e32: 'e32_2_2_', e33: 'e33_2_2_' },
{ e31: 'e31_2_3_', e32: 'e32_2_3_' },
], ],
e4: 'e4_2____', e4: 'e4_2____',
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment