Module: Transproc::ArrayTransformations

Extended by:
Registry
Defined in:
lib/transproc/array.rb

Overview

Transformation functions for Array objects

Examples:

require 'transproc/array'

include Transproc::Helper

fn = t(:map_array, t(:symbolize_keys)) >> t(:wrap, :address, [:city, :zipcode])

fn.call(
  [
    { 'city' => 'Boston', 'zipcode' => '123' },
    { 'city' => 'NYC', 'zipcode' => '312' }
  ]
)
# => [{:address=>{:city=>"Boston", :zipcode=>"123"}}, {:address=>{:city=>"NYC", :zipcode=>"312"}}]

Constant Summary collapse

CACHE =
Hash.new { |h, k| h[k] = {} }

Class Method Summary collapse

Methods included from Registry

[], contain?, fetch, import, register, store

Class Method Details

.add_keys(array, keys) ⇒ Array

Adds missing keys with nil value to all tuples in array



218
219
220
221
# File 'lib/transproc/array.rb', line 218

def self.add_keys(array, keys)
  base = keys.inject({}) { |a, e| a.merge(e => nil) }
  map_array(array, ->(v) { base.merge(v) })
end

.combine(array, mappings, cache = CACHE.dup) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/transproc/array.rb', line 123

def self.combine(array, mappings, cache = CACHE.dup)
  root, groups = array

  root.map do |parent|
    child_hash = {}

    for candidates in groups
      index = groups.index(candidates)
      data = mappings[index]

      key = data[0]
      keys = data[1]

      children =
        if data.size == 2
          candidates
        else
          combine(candidates, data[2])
        end

      child_keys = keys.size > 1 ? keys.values : keys.values[0]
      pk_names = keys.size > 1 ? keys.keys : keys.keys[0]

      pkey_value =
        if pk_names.is_a?(Array)
          parent.values_at(*pk_names)
        else
          parent[pk_names]
        end

      cache[key][child_keys] ||= children.group_by do |child|
        if child_keys.is_a?(Array)
          child.values_at(*child_keys)
        else
          child[child_keys]
        end
      end

      child_arr = cache[key][child_keys][pkey_value] || []

      child_hash[key] = child_arr
    end

    parent.merge(child_hash)
  end
end

.extract_key(array, key) ⇒ Array

Converts the array of hashes to array of values, extracted by given key

Examples:

fn = t(:extract_key, :name)
fn.call [
  { name: 'Alice', role: 'sender' },
  { name: 'Bob', role: 'receiver' },
  { role: 'listener' }
]
# => ['Alice', 'Bob', nil]


187
188
189
# File 'lib/transproc/array.rb', line 187

def self.extract_key(array, key)
  map_array(array, ->(v) { v[key] })
end

.group(array, key, keys) ⇒ Array

Group array values using provided root key and value keys

Examples:

fn = Transproc(:group, :tags, [:tag_name])

fn.call [
  { task: 'Group it', tag: 'task' },
  { task: 'Group it', tag: 'important' }
]
# => [{ task: 'Group it', tags: [{ tag: 'task' }, { tag: 'important' }]]


82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/transproc/array.rb', line 82

def self.group(array, key, keys)
  grouped = Hash.new { |h, k| h[k] = [] }
  array.each do |hash|
    hash = Hash[hash]

    old_group = Coercions.to_tuples(hash.delete(key))
    new_group = keys.inject({}) { |a, e| a.merge(e => hash.delete(e)) }

    grouped[hash] << old_group.map { |item| item.merge(new_group) }
  end
  grouped.map do |root, children|
    root.merge(key => children.flatten)
  end
end

.insert_key(array, key) ⇒ Array

Wraps every value of the array to tuple with given key

The transformation partially inverses the extract_key.

Examples:

fn = t(:insert_key, 'name')
fn.call ['Alice', 'Bob', nil]
# => [{ 'name' => 'Alice' }, { 'name' => 'Bob' }, { 'name' => nil }]


206
207
208
# File 'lib/transproc/array.rb', line 206

def self.insert_key(array, key)
  map_array(array, ->(v) { { key => v } })
end

.map_array(array, fn) ⇒ Array

Map array values using transformation function

Examples:


fn = Transproc(:map_array, -> v { v.upcase })

fn.call ['foo', 'bar'] # => ["FOO", "BAR"]


40
41
42
# File 'lib/transproc/array.rb', line 40

def self.map_array(array, fn)
  Array(array).map { |value| fn[value] }
end

.ungroup(array, key, keys) ⇒ Array

Ungroup array values using provided root key and value keys

Examples:

fn = Transproc(:group, :tags, [:tag_name])

fn.call [
  { task: 'Group it', tags: [{ tag: 'task' }, { tag: 'important' }]
]
# => [
  { task: 'Group it', tag: 'task' },
  { task: 'Group it', tag: 'important' }
]


117
118
119
# File 'lib/transproc/array.rb', line 117

def self.ungroup(array, key, keys)
  array.flat_map { |item| HashTransformations.split(item, key, keys) }
end

.wrap(array, key, keys) ⇒ Array

Wrap array values using HashTransformations.nest function

Examples:

fn = Transproc(:wrap, :address, [:city, :zipcode])

fn.call [{ city: 'NYC', zipcode: '123' }]
# => [{ address: { city: 'NYC', zipcode: '123' } }]


59
60
61
62
# File 'lib/transproc/array.rb', line 59

def self.wrap(array, key, keys)
  nest = HashTransformations[:nest, key, keys]
  map_array(array, nest)
end