Flatten a Ruby Array without using built-in 'flatten' method [closed] - ruby

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
Common way to solve this problem is using flatten method.
Can this be done in other ways, say by not using flatten?
def flatten_array(arr)
return arr.flatten
end
print flatten_array([1,2,3,4,[1,2,3,4],5])

class Array
def flattify
each_with_object([]) do |element, flattened|
flattened.push *(element.is_a?(Array) ? element.flattify : element)
end
end
end
[1,2,3,4,[1,2,3,4],5].flattify # => [1, 2, 3, 4, 1, 2, 3, 4, 5]
A non-monkey patching Array version:
def flattify(array)
array.each_with_object([]) do |element, flattened|
flattened.push *(element.is_a?(Array) ? flattify(element) : element)
end
end
flattify([1,2,3,4,[1,2,3,4],5]) # => [1, 2, 3, 4, 1, 2, 3, 4, 5]

Using recursion to solve this problem.
class ArrayConvert
def self.flatten_array(array,init)
array.each do |a|
if a.class==Array
flatten_array(a,init)
else
init << a
end
end
init
end
p flatten_array([1, 2, 3, 4, [1, 2, 3, 4], 5],[])
end

Related

Finding paths in an adjacency list [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
What is the optimal algorithm to find all the paths between 2 nodes of an adjacency list
Example input:
source = 1
destination = 5
list = {1: [2], 2: [4], 3: [4, 5], 4: [5]}
def paths(adj, st, en)
return [] unless adj.key?(st)
adj[st].each_with_object([]) do |nxt,arr|
nxt == en ? arr << [st, en] :
paths(adj, nxt, en).each { |a| arr << [st, *a] }
end
end
adj = { 1=>[2,3], 2=>[4,7], 3=>[4,8], 4=>[5,6], 5=>[7], 6=>[7] }
Note that I added an isolated node 8.
paths(adj, 1, 7)
#=> [[1, 2, 4, 5, 7],
# [1, 2, 4, 6, 7],
# [1, 2, 7],
# [1, 3, 4, 5, 7],
# [1, 3, 4, 6, 7]]

Array into ranges of consecutive numbers [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am trying to make a Ruby function that converts an array of unique numbers into ranges of consecutive numbers.
[1, 2, 3, 5, 6, 8, 9] => [(1..3), (5..6), (8..9)]
It doesn't seem too hard, but I want to know if there's better way.
How is this using Enumerable#slice_before?
ar = [1, 2, 3, 5, 6, 8, 9]
prev = ar[0]
p ar.slice_before { |e|
prev, prev2 = e, prev
prev2 + 1 != e
}.map{|a| a[0]..a[-1]}
# >> [1..3, 5..6, 8..9]
ar = [1, 2, 3, 5, 6,7, 8, 9,11]
prev = ar[0]
p ar.slice_before { |e|
prev, prev2 = e, prev
prev2 + 1 != e
}.map{|a| a[0]..a[-1]}
# >> [1..3, 5..9, 11..11]
This is something I wrote a while back when dealing with IP address ranges:
class Array
# [1,2,4,5,6,7,9,13].to_ranges # => [1..2, 4..7, 9..9, 13..13]
# [1,2,4,5,6,7,9,13].to_ranges(true) # => [1..2, 4..7, 9, 13]
def to_ranges(non_ranges_ok=false)
self.sort.each_with_index.chunk { |x, i| x - i }.map { |diff, pairs|
if (non_ranges_ok)
pairs.first[0] == pairs.last[0] ? pairs.first[0] : pairs.first[0] .. pairs.last[0]
else
pairs.first[0] .. pairs.last[0]
end
}
end
end
if ($0 == __FILE__)
require 'awesome_print'
ary = [1, 2, 4, 5, 6, 7, 9, 13, 12]
puts ary.join(', ')
ap ary.to_ranges
ary = [1, 2, 4, 8, 5, 6, 7, 3, 9, 11, 12, 10]
puts ary.join(', ')
ap ary.to_ranges
end
Pass true to to_ranges and it will not convert individual elements into one-element ranges.
Here's a solution to the same question you're asking. The linked code does a bit more work than you require (the numbers don't need to be sorted, or consecutive), but it'll do the trick. Or, you could use this code, suggested by #NewAlexandria :
class Array
def to_ranges
compact.sort.uniq.inject([]) do |r,x|
r.empty? || r.last.last.succ != x ? r << (x..x) : r[0..-2] << (r.last.first..x)
end
end
end

Array of IDs to array of function results [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I currently have this code
def objects(ids)
array = []
ids.each do |id|
array << object(id) # => #<object[id]>
end
array
end
objects([1, 2, 3])
# => [#<object1>, #<object2>, #<object3>]
It seems like there should be a cleaner way to do this. Can anyone help?
EDIT
This is what works
[1, 2, 3].map do |id|
object(id)
end
ORIGINAL
go this way:
[1, 2, 3].map(&:object_id)
# => [3, 5, 7]
def objects(ids)
ids.map(&:object_id)
end
objects([1, 2, 3])
# => [3, 5, 7]

Why am I having trouble creating a custom array method that returns a hash with indices of matching array values? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I'm trying to monkey patch the Array class with a method that, when passed something like [1, 3, 4, 3, 0, 3, 1], will return a hash with { 1 => [0, 6], 3 => [1, 3, 5] }, where the key is the number we are matching to, and the value is an array with the indices of all matches.
Here's the code I have so far. I can't tell why it's returning something like {1=>[0, 2, 3, 1, 2, 0], 3=>[0, 2, 3, 1, 2, 0], 0=>[0, 2, 3, 1, 2, 0]}:
class Array
def dups
matches = {}
matches_index = []
self.each do |i|
self[(i_index + 1)..-1].each_with_index do |j, j_index|
matches_index << j_index if self[i] == self[j]
end
matches[i] = matches_index
end
matches.keep_if { |key, value| value.length > 1 }
end
end
This is an even shorter version:
class Array
def dups
each_index.group_by{|i| self[i]}.select{|k,v| v.size > 1}
end
end
Your code looks very complicated (and very imperative). A functional approach is way easier:
class Array
def dups
grouped_indexed = each_with_index.group_by(&:first)
Hash[grouped_indexed.map { |x, gs| [x, gs.map(&:last)] }]
end
end
Is this still too complicated? well, yes, but that's because the core is missing some basic abstractions like map_by:
require 'facets'
xs = [1, 3, 4, 3, 0, 3, 1]
xs.each_with_index.to_a.map_by { |x, i| [x, i] }
#= {1=>[0, 6], 3=>[1, 3, 5], 4=>[2], 0=>[4]}
To be honest, even that one-liners is too verbose. With the right abstractions we should be able to write something like this:
require 'awesome_functional_extensions'
xs = [1, 3, 4, 3, 0, 3, 1]
xs.with_index.group_by_pair
#= {1=>[0, 6], 3=>[1, 3, 5], 4=>[2], 0=>[4]}
To improve on Stas S already excellent solution:
class Array
def dups
(self.each_index.group_by {|i| self[i]}).keep_if{|k, v| v.size > 1}
end
end
Which results in an array of only duplicates.
class Array
def dups
matches = {}
self.each_with_index do |v, i|
matches.has_key?(v) ? matches[v] << i : matches[v] = [i]
end
matches
end
end
x = [1, 3, 4, 3, 0, 3, 1]
puts x.dups
Yet another version:
class Array
def dups
to_enum
.with_index
.group_by(&:first)
.select{|_, a| a.length > 1}
.each_value{|a| a.map!(&:last)}
end
end

checking if 2 numbers of array add up to Input number in ruby [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am new to ruby on rails .
I was programming ruby and want to try checking if 2 numbers of array add up to Input number in ruby.
eg,
array A[]= {3, 1, 8, 11, 5, 7}
given integer say N = 6
answer will be 1,5.
I know how to program it in java,C++ but i am stuck in ruby coding,
Can anyone please help me.Thanks in advance
You can use Array#combination:
ary = [3, 1, 8, 11, 5, 7]
n = 6
ary.combination(2).detect { |a, b| a + b == n }
#=> [1, 5]
combination(2) creates an array of all combinations of length 2, i.e. [3,1], [3,8], [3,11] etc.
detect { |a, b| a + b == n } returns the first pair with sum n
You can use find_all instead of detect to return all pairs with sum n.
a = [3, 1, 8, 11, 4, 5, 7, 2]
> a.combination(2).select {|i| i.inject(:+) == 6 }
#=> [[1, 5], [4, 2]]
a = [3, 1, 8, 11, 5, 7]
p a.combination(2).find{|i| i.inject(:+) == 6}
# >> [1, 5]

Resources