7

i want to know if it's possible to push in array with auto-creation of array if doesn't exist already, like in PHP:

$toto[] = 'titi';

if $toto is not already defined, it will create array and push 'titi' into. If already exist, it will just push.

in Ruby i have to do:

toto ||= []
toto.push('titi')

It's possible to do this in one line?

Because if i have an loop, it will test "||=" for nothing except the first time:

Person.all.each do |person|    
   toto ||= [] #with 1 billion of person, this line is useless 999 999 999 times...
   toto.push(person.name)

have you a better solution?

thx.

8
  • 3
    Why don't you put that line outside the loop? Commented Dec 13, 2013 at 15:53
  • @rohit89 you can put it as an answer Commented Dec 13, 2013 at 16:06
  • 1
    if i do that, and they are 0 Person, the array will exist [] instead of to be nil Commented Dec 13, 2013 at 16:10
  • 1
    @Matrix does that really hurt so much? toto = [] unless Person.empty? Commented Dec 13, 2013 at 16:11
  • if i test: "if toto", the result not the same. false positive if toto = [] Commented Dec 13, 2013 at 16:13

5 Answers 5

5
toto = Person.all.reduce([]) do |arr, person|
  arr << person.name
end

or you could simply pluck the names if they come from the DB

toto = Person.pluck(:name) # SELECT `people.name` FROM `people`
Sign up to request clarification or add additional context in comments.

5 Comments

Note: this only works because Array#<< returns self
What's the difference between pluck and map except the latter requires an extra pretzel?
@JanDvorak map Person.all will initialize entire DB rows as AR objects where Person.pluck(:name) does something like SELECT people.name FROM people
so, the difference is pluck acts before the database query takes place, and builds the query?
@JanDvorak yes - similar to Person.count
4

In a single line it will be as:

toto = (toto || [] ) << 'titi'

and for Person name:

toto = (toto || [] ) << person.name

If you don't need to rewrite the Array do as follows:

( toto ||= [] ) << 'titi'

1 Comment

if you do that, you overwrite the array. sry i don't see your edit, but you write it in one line, but the test is alwais here...
3

In this case I'd just go straight to each_with_object:

toto = Person.all.each_with_object([]) do |person, toto|
  toto.push(person.name)
end

Alternatively, you could just map it:

toto = Person.all.map(&:name)

Comments

2

I will do as below :

toto = toto.to_a + Person.all.map(&:name)

3 Comments

Why the extra toto.to_a and concatenation?
@muistooshort in case toto was non-empty before the loop
@muistooshort Jan Dvorak is right.. But to consider this, if toto not exist, then to avoid error no method, I applied nil#to_a which will give [].
0

if $toto is not already defined, it will create array and push 'titi' into. If already exist, it will just push.

in Ruby i have to do:

toto ||= [] toto.push('titi') It's possible to do this in one line?

Yes answer is:

toto ||= Array.new(1, 'titi')

Because if i have an loop, it will test "||=" for nothing except the first time:

Person.all.each do |person|    
  toto ||= [] #with 1 billion of person, this line is useless 999 999 999 times...
  toto.push(person.name)
end

have you a better solution?

you can use it simple with:

toto ||= Person.all.collect(&:name)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.