Class: ObjectTable::Grouping

Inherits:
Object
  • Object
show all
Includes:
Factory::SubFactory
Defined in:
lib/object_table/grouping.rb,
lib/object_table/grouping/grid.rb

Defined Under Namespace

Classes: Grid

Constant Summary collapse

DEFAULT_VALUE_PREFIX =
'v_'.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parent, *columns, &grouper) ⇒ Grouping

Returns a new instance of Grouping.



19
20
21
22
23
24
# File 'lib/object_table/grouping.rb', line 19

def initialize(parent, *columns, &grouper)
  @parent = parent
  @grouper = grouper
  @columns = columns
  @names = columns
end

Class Method Details

.generate_name(prefix, names) ⇒ Object



93
94
95
96
97
# File 'lib/object_table/grouping.rb', line 93

def self.generate_name(prefix, names)
  regex = Regexp.new(Regexp.quote(prefix) + '(\d+)')
  i = names.map{|n| n =~ regex and $1.to_i}.compact.max || -1
  "#{prefix}#{i + 1}"
end

.key_struct(names) ⇒ Object



99
100
101
# File 'lib/object_table/grouping.rb', line 99

def self.key_struct(names)
  Struct.new(*names.map(&:to_sym))
end

Instance Method Details

#_keysObject



26
27
28
29
30
31
32
33
34
35
36
# File 'lib/object_table/grouping.rb', line 26

def _keys
  return Util.get_rows(@parent, @columns) unless @columns.empty?

  keys = @parent.apply(&@grouper)
  raise 'Group keys must be hashes' unless keys.is_a?(Hash)
  keys = BasicGrid.new.replace keys
  keys._ensure_uniform_columns!(@parent.nrows)

  @names = keys.keys
  keys.values.map(&:to_a).transpose
end

#_make_groups(groups) ⇒ Object



85
86
87
88
89
90
91
# File 'lib/object_table/grouping.rb', line 85

def _make_groups(groups)
  key_struct = self.class.key_struct(@names)
  groups.each do |k, v|
    yield __group_cls__.new(@parent, key_struct.new(*k), NArray.to_na(v))
  end
  @parent
end

#apply(&block) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/object_table/grouping.rb', line 44

def apply(&block)
  groups = Util.group_indices(_keys)
  return empty_aggregation if groups.empty?

  value_key = self.class.generate_name(DEFAULT_VALUE_PREFIX, @names).to_sym
  keys = []

  data = groups.keys.zip(to_enum(:_make_groups, groups)).map do |key, group|
    value = Util.apply_block(group, block)

    case value
    when TableMethods
      nrows = value.nrows
    when BasicGrid
      nrows = value._ensure_uniform_columns!
    else
      nrows = (Column.length_of(value) or 1)
      value = BasicGrid[value_key, value]
    end

    keys.concat( Array.new(nrows, key) )
    value
  end

  keys = BasicGrid[@names.zip(keys.transpose)]
  result = __table_cls__._stack(data)
  __table_cls__.new(keys.merge!(result.columns))
end

#each(&block) ⇒ Object



38
39
40
41
42
# File 'lib/object_table/grouping.rb', line 38

def each(&block)
  groups = Util.group_indices(_keys)
  return to_enum(:_make_groups, groups) unless block
  _make_groups(groups){|grp| Util.apply_block(grp, block)}
end

#empty_aggregationObject



103
104
105
# File 'lib/object_table/grouping.rb', line 103

def empty_aggregation
  __table_cls__.new(@names.map{|n| [n, []]})
end

#reduce(defaults = {}, &block) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
# File 'lib/object_table/grouping.rb', line 73

def reduce(defaults={}, &block)
  keys = _keys()
  return empty_aggregation if keys.empty?

  grid = Grid.new(keys, defaults)
  rows = @parent.each_row(row_factory: Grid::RowFactory)
  grid.apply_to_rows(rows, self.class.key_struct(@names), block)

  keys = BasicGrid[@names.zip(grid.index.keys.transpose)]
  __table_cls__.new(keys.merge!(grid.values))
end