Class: ObjectTable::Grouped

Inherits:
Object
  • Object
show all
Includes:
TableChild
Defined in:
lib/object_table/grouped.rb

Constant Summary collapse

DEFAULT_VALUE_PREFIX =
'v_'

Class Method Summary collapse

Instance Method Summary collapse

Methods included from TableChild

#__group_cls__, #__static_view_cls__, #__table_cls__, #__view_cls__

Constructor Details

#initialize(parent, *names, &grouper) ⇒ Grouped

Returns a new instance of Grouped.



8
9
10
11
12
# File 'lib/object_table/grouped.rb', line 8

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

Class Method Details

._generate_name(prefix, existing_names) ⇒ Object



85
86
87
88
89
# File 'lib/object_table/grouped.rb', line 85

def self._generate_name(prefix, existing_names)
  regex = Regexp.new(Regexp.quote(prefix) + '(\d+)')
  i = existing_names.map(&regex.method(:match)).compact.map{|match| match[-1].to_i}.max || -1
  "#{prefix}#{i + 1}"
end

Instance Method Details

#_groupsObject



14
15
16
17
18
19
20
21
# File 'lib/object_table/grouped.rb', line 14

def _groups
  names, keys = _keys()
  groups = keys.length.times.group_by{|i| keys[i]}
  groups.each do |k, v|
    groups[k] = v
  end
  [names, groups]
end

#_keysObject



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

def _keys
  if @names.empty?
    keys = @parent.apply(&@grouper)
    raise 'Group keys must be hashes' unless keys.is_a?(Hash)
    keys = ObjectTable::BasicGrid.new.replace keys
    keys._ensure_uniform_columns!(@parent.nrows)
  else
    keys = ObjectTable::BasicGrid[@names.map{|n| [n, @parent.get_column(n)]}]
  end

  names = keys.keys
  keys = keys.values.map(&:to_a).transpose
  [names, keys]
end

#_make_groups(names, groups) ⇒ Object



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

def _make_groups(names, groups)
  key_struct = Struct.new(*names.map(&:to_sym))
  enumerator = Enumerator.new do |y|
    groups.each do |k, v|
      y.yield __group_cls__.new(@parent, key_struct.new(*k), v)
    end
    @parent
  end
end

#apply(&block) ⇒ Object



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
72
# File 'lib/object_table/grouped.rb', line 45

def apply(&block)
  names, groups = _groups()
  value_key = self.class._generate_name(DEFAULT_VALUE_PREFIX, names).to_sym
  nrows = []

  data = _make_groups(names, groups).map do |group|
    value = group._apply_block(&block)

    case value
    when ObjectTable::TableMethods
      nrows.push(value.nrows)
      value = value.columns
    when ObjectTable::BasicGrid
      nrows.push(value._ensure_uniform_columns!)
    else
      nrows.push( (ObjectTable::Column.length_of(value) rescue 1) )
    end

    value = ObjectTable::BasicGrid[value_key, value] unless value.is_a?(ObjectTable::BasicGrid)
    value
  end

  keys = groups.keys.transpose.map{|col| col.zip(nrows).flat_map{|key, rows| [key] * rows}}
  keys = ObjectTable::BasicGrid[names.zip(keys)]

  result = __table_cls__.stack(*data)
  __table_cls__.new(keys.merge!(result.columns))
end

#each(&block) ⇒ Object



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

def each(&block)
  names, groups = _groups()
  enumerator = _make_groups(names, groups)
  return enumerator unless block
  enumerator.each{|grp| grp._apply_block(&block)}
end