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"}}]

API:

  • public

Class Method Summary collapse

Methods included from Registry

[], fetch, import, store

Class Method Details

.add_keys(array, keys) ⇒ Array

Adds missing keys with nil value to all tuples in array

Parameters:

Returns:

API:

  • public



243
244
245
# File 'lib/transproc/array.rb', line 243

def self.add_keys(array, keys)
  add_keys!(Array[*array], keys)
end

.add_keys!(array, keys) ⇒ Object

Same as add_keys but mutates the array

See Also:

API:

  • public



252
253
254
255
# File 'lib/transproc/array.rb', line 252

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) ⇒ Array<Hash>

Combines two arrays by merging child items from right array using join keys

Examples:

fn = t(:combine, [[:tasks, name: :user]])

fn.call([[{ name: 'Jane' }], [{ user: 'Jane', title: 'One' }]])
# => [{:name=>"Jane", :tasks=>[{:user=>"Jane", :title=>"One"}]}]

Parameters:

  • The input array

  • The mapping definitions array

Returns:

API:

  • public



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
169
170
171
172
173
174
175
# File 'lib/transproc/array.rb', line 144

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

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

  root.map { |parent|
    child_hash = {}

    groups.each_with_index do |candidates, index|
      key, keys, group_mappings = mappings[index]

      children =
        if group_mappings
          combine(candidates, group_mappings)
        else
          candidates
        end

      child_keys = keys.values
      pkey_value = parent.values_at(*keys.keys) # ugh

      cache[key][child_keys] ||= children.group_by { |child|
        child.values_at(*child_keys)
      }
      child_arr = cache[key][child_keys][pkey_value] || []

      child_hash.update(key => child_arr)
    end

    parent.merge(child_hash)
  }
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]

Parameters:

  • The input array of hashes

  • The key to extract values by

Returns:

API:

  • public



194
195
196
# File 'lib/transproc/array.rb', line 194

def self.extract_key(array, key)
  extract_key!(Array[*array], key)
end

.extract_key!(array, key) ⇒ Object

Same as extract_key but mutates the array

See Also:

API:

  • public



203
204
205
# File 'lib/transproc/array.rb', line 203

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' }]]

Parameters:

  • The input array

  • The nesting root key

  • The nesting value keys

Returns:

API:

  • public



91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/transproc/array.rb', line 91

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 }]

Parameters:

  • The input array of hashes

  • The key to extract values by

Returns:

API:

  • public



222
223
224
# File 'lib/transproc/array.rb', line 222

def self.insert_key(array, key)
  insert_key!(Array[*array], key)
end

.insert_key!(array, key) ⇒ Object

Same as insert_key but mutates the array

See Also:

API:

  • public



231
232
233
# File 'lib/transproc/array.rb', line 231

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"]

Parameters:

  • The input array

  • The transformation function

Returns:

API:

  • public



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

def self.map_array(array, fn)
  map_array!(Array[*array], fn)
end

.map_array!(array, fn) ⇒ Object

Same as map_array but mutates the array

See Also:

API:

  • public



49
50
51
# File 'lib/transproc/array.rb', line 49

def self.map_array!(array, fn)
  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' }
]

Parameters:

  • The input array

  • The nesting root key

  • The nesting value keys

Returns:

API:

  • public



126
127
128
# File 'lib/transproc/array.rb', line 126

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' } }]

Parameters:

  • The input array

  • The nesting root key

  • The nesting value keys

Returns:

API:

  • public



68
69
70
71
# File 'lib/transproc/array.rb', line 68

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