N N
N N

Reputation: 1638

How can I modify content of an array in one loop

I have an array that looks like this:

strings= ['','','','   Some text', '', '     Some another text']

how can I map striped text only? right now I am doing this:

strings.select!{|string| !string.emtpy?}
strings.map!{|string| string.strip}

as you can see there are 2 loops. which I think is not efficient

Upvotes: 0

Views: 102

Answers (5)

NEHAL AMIN
NEHAL AMIN

Reputation: 121

 `strings.map {|string| string.strip if string.strip.size > 0}`.compact

> ["Some text", "Some another text"]

Explanation:

strings.map {|string| string.strip if string.strip.size > 0}

It will return:

> [nil, nil, nil, "Some text", nil, "Some another text"]

nil in case when string is empty. Else it will return stripped text.

.compact: Returns a copy of self with all nil elements removed.

So, [nil, nil, nil, "Some text", nil, "Some another text"].compact will be:> ["Some text", "Some another text"]

Upvotes: 1

Natan Rubinstein
Natan Rubinstein

Reputation: 665

This is not most memory efficient (because you create another array) buy will do the job in one loop (There may be shorter ways to write this code. I am also using text!='' instead emtpy?because I do not use Rails

strings = ['','','','   Some text', '', '     Some another text']
stripped_strings = []
strings.each do |text|
if !(text=='')
   stripped_strings << text.strip
end
puts stripped_strings

Output will be ['Some text','Some another text']

The next way works for me in Ruby 2.1.7 I am not sure it will work in other versions. And I think it is a little risky. But you will not need an extra Array

strings = ['','','','   Some text', '', '     Some another text']
strings.select! do |text|
    text.strip!
    text != ''
end

This works because that Ruby treats the String as an Object. Tell me comment If you want more explanation on this

A third option is also a little risky would be to delete the elements from the array while iterating on it. For this I am not using string.each because removing items from array while running the each can be problematic also. Now I do not need to worry whether the each is cloning the the |text| (then the strip! will not change the original array like in previous example)

strings = ['','','','   Some text', '', '     Some another text']
$i = strings.length - 1
while $i >= 0 do
  if strings[$i] == ''
    strings.delete_at($i)
  else
    strings[$i].strip!
  end
  $i -= 1
end
puts strings

Upvotes: 0

Radix
Radix

Reputation: 2747

You can also achieve that with #inject (SO link, Ruby doc link) with one loop:

strings.inject([]) { |arr, val| val.present? ? arr.push(val.strip) : arr }

Upvotes: 0

Sagar Pandya
Sagar Pandya

Reputation: 9497

You can use grep here:

strings.grep(/.+/, &:strip)
 #=> ["Some text", "Some another text"]

Upvotes: 1

Igor Drozdov
Igor Drozdov

Reputation: 15045

You can just add lazy not to create an intermediate array for every step. It is still 2 iterations, but memory efficient, yet readable

strings.lazy.select {|string| !string.empty? }.map {|string| string.strip }.to_a

Upvotes: 1

Related Questions