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

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:

  • keys (Array)

Returns:

  • (Array)

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:


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:

  • array (Array<Array>)

    The input array

  • mappings (Array<Hash>)

    The mapping definitions array

Returns:

  • (Array<Hash>)

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:

  • array (Array<Hash>)

    The input array of hashes

  • key (Object)

    The key to extract values by

Returns:

  • (Array)

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:


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:

  • array (Array)

    The input array

  • key (Object)

    The nesting root key

  • keys (Object)

    The nesting value keys

Returns:

  • (Array)

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:

  • array (Array<Hash>)

    The input array of hashes

  • key (Object)

    The key to extract values by

Returns:

  • (Array)

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:


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:

  • array (Array)

    The input array

  • fn (Proc)

    The transformation function

Returns:

  • (Array)

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:


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:

  • array (Array)

    The input array

  • key (Object)

    The nesting root key

  • keys (Object)

    The nesting value keys

Returns:

  • (Array)

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:

  • array (Array)

    The input array

  • key (Object)

    The nesting root key

  • keys (Object)

    The nesting value keys

Returns:

  • (Array)

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