How to initialize objects with different object_id in Ruby? - ruby

If I initialize objects with assignment like a = b = c = []
then this variables have the same object_ids: a.object_id == b.object_id == c.object_id
Also I tried:
[a, b, c].map {|e| e = [] }
a, b, c = Array.new(3, [])
a, b, c = Array.new(3, Array.new)
but it doensn't initialize a, b, c variables with different object_ids
Is there a way to initialize variables a, b, c with different object ids but with the same value == []?

How about these possible solutions:
a,b,c=[],[],[]
a,b,c=(0..2).map{[]}
a,b,c=Array.new(3){[]}

How about this?
a = []
b = []
c = []

Related

Why does this method return three values?

I have following Ruby programm:
def swap (a,b)
return a,b = b,a
end
puts swap(5,3)
I expected the output.
3
5
But I get.
5
3
5
What's the reason?
Thanks!
Why does this method return three values?
It's because of the return statement, Ruby tries to interpret the right-hand side as an array and your code:
return a,b = b,a
gets evaluated as: (parentheses added for clarity)
return [a, (b=b), a]
i.e. a 3-element array [a, b, a] (assigning b to itself does nothing)
Remove the keyword return. It is actually doing: return a, (b), a. Where (b = b)
def swap(a,b)
a, b = b, a
end
puts swap(5,3)
Output
=> 3, 5
In your program: in swap function the return you have given is return a,b = b,a
remove a,band diretcly write return b,a.
you will get your expected output.
Reason:
in return a,b = b,a is return first the value of a then executing b=b,a.
Hope this might help you out
def swap (a,b)
return b,a
end
puts swap(5,3)
Output
3
5

Equality test on three or more objects

If I have three or more objects like so:
a = 4
b = 4
c = 4
d = 2
what would be a clean ruby-style way of determining whether they are all equal? Any bespoke methods for running equality tests on three or more elements?
I suppose I could do something like this:
arrays = [a,b,c,d].map{|x| [x]}
arrays.first == arrays.reduce(:&) ? true : false
which appears to work, but feels sort of ham handed, and might be difficult for other developers to read.
[a,b,c,d].any?{|x| x != a}
or
array.any?{|x| x != array.first}
Alternatively, the #all? method may read more intuitively for some:
array.all? {|x| x == array.first }
[a, b, c, d].group_by(&:itself).length == 1
# => false
or
[a, b, c, d].chunk(&:itself).to_a.length == 1
# => false
or
[a, b, c, d].chunk_while(&:==).to_a.length == 1
# => false
or the naive:
[a, b, c, d].uniq.length == 1
I was reminded of one?. Provided that you do not have any falsy element, the above can be written:
[a, b, c, d].uniq.length.one?
I think the answer by #kipar is better by all means, but for the sake of “doing it the way you started” I would post this here:
[a, b, c, d].reduce { |r, e| r == e && r } && true

Passing return value into another method

I am starting with an array of letters:
letters = %w[c s t p b l f g d m
y o u i h t r a e l
o t l a e m r s n i
m a y l p x s e k d]
Passing them, finding all combinations that return an array like this ["cstp", "cstb", "cstl"], this is a shortened example.
def combinations(letters)
combos = letters.combination(4)
combos.collect do |letter_set|
letter_set.join(",").gsub("," ,"")
end
end
I am trying to figure out how to pass the return value of combinations into start_wtih_letter_c. Do I have to pass a block like &block? I tried various things that keep saying wrong number of arguments.
def start_with_letter_c(pass the return value)
combinations.select {|word| word.match(/^ca/) }
end
Here you go, no errors:
letters = %w[c s t p b l f g d m
y o u i h t r a e l
o t l a e m r s n i
m a y l p x s e k d]
def combinations(letters)
combos = letters.combination(4)
combos.collect do |letter_set|
letter_set.join(",").gsub("," ,"")
end
end
def start_with_letter_c(combinations)
combinations.select {|word| word.match(/^ca/) }
end
start_with_letter_c(combinations(letters))
# => ["cael", "caeo", "caet", "cael", "ca ...and so on
I would write something like this:
letters = %w[c s t p b l f g d m
y o u i h t r a e l
o t l a e m r s n i
m a y l p x s e k d]
def combinations(letters)
letters.combination(4).map(&:join)
end
def start_with_letter_c(combinations)
combinations.select { |word| word.start_with?('ca') }
end
start_with_letter_c(combinations(letters))

How can I get "x" objects before a given object?

It's better to explain this in pseudo-code, I want to do this:
limit_object = Model.first(id: bla)
objects = Model.all(constraint: limit_object, limit: 30)
If the objects are:
[a, b, c, d, e, f, g]
and limit_object is 'c', it should return:
[a, b, c]
Is there a way to do this in DataMapper?
Okay, I found it:
quotes = Model.all(:for_date.lte => date, limit: 10)

Create many arrays in one line

I need to do something like the following
e = []
m = []
p = []
t = []
...and so on for about 10 different arrays
Is there a way to create all these arrays on one line?
You can do it using the following:
e,m,p,t... = Array.new(10) { [] }
It turns out
[[]]*10
is not the right way to go, [[]]*10 is for repetition and is just repeating the same object [] 10 times, so all the variables would end up getting assigned to the same object.
Like multiple variable declaration in one line a1, a2, a3 = 3, 10, 4
e, m, p, t ... = [], [], [], [] ...
I'm curious at what are those 10 different arrays, because I would suspect they shouldn't be 10 different variables but just one. You don't give any context, so I can only guess, something like the following might better:
whatever = Hash.new{|h, k| h[k] = []}
whatever[:e] # => []
whatever[:m] << 42
whatever[:m] # => [42]
# etc...
Otherwise, as zomboid wrote:
e, m, p, t ... = [], [], [], [] ...
What all fails
> p, q, r = v = Array.new(3, [])
=> [[], [], []]
> v.map(&:object_id)
=> [70155104393020, 70155104393020, 70155104393020]
> p = q = r = []
=> []
> [p, q, r].map(&:object_id)
=> [70155104367380, 70155104367380, 70155104367380]
What works
> p, q, r = v = Array.new(3){ [] }
=> [[], [], []]
> v.map(&:object_id)
=> [70155104731780, 70155104731760, 70155104731740]

Resources