Is there a starightforward way to achieve array.join(", ") where the comma is only included between elements that exist? I.e., if some elements don't exist in the array, I don't end up getting orphan commas?
Example:
["", nil, "test word", 5, 7, nil, "", nil, "", 7, 6, ""] => "test word, 5, 7, 7, 6"
Edit: Please note that the first method here requires Ruby on Rails. Use the second method for a Ruby-only solution
You can try this to remove both nil and empty strings "" and then join with commas (It removes all nil values with compact, then it does split on "" to create a two-dimensional array where any "" elements in the first array are just empty arrays in the new 2D array, then it does flatten which turns the 2D array back into a normal array but with all the empty arrays removed, and finally it does the join(", ") on this array):
> array.compact.split("").flatten.join(", ")
array = ["", nil, "test word", 5, 7, nil, "", nil, "", 7, 6, ""]
array.compact => ["", "test word", 5, 7, "", "", 7, 6, ""].split("") => [[], ["test word", 5, 7], [], [7, 6], []].flatten => ["test word", 5, 7, 7, 6].join(", ") => "test word, 5, 7, 7, 6"
Edit: Another way would be:
> array.reject(&:blank?).join(", ")
array = ["", nil, "test word", 5, 7, nil, "", nil, "", 7, 6, ""]
array.reject(&:blank?) => ["test word", 5, 7, 7, 6].join(", ") => "test word, 5, 7, 7, 6"
I think you have nil elements in your array. You can do this:
arr.compact.join(", ")
It seems you need to compact the array before join. It returns a copy of array without nil elements.
http://ruby-doc.org/core-2.2.0/Array.html#method-i-compact
[1,nil,2,3].compact.join(', ')
You can also use compact! to remove the nil elements from the source array itself (without making a copy).
This answer will join all array elements except nil from a nested array as well as a flat array:
[1, nil, 3, [:a, nil, :c], 5, nil, 7].flatten.compact.join(',')
=> "1,3,a,c,5,7"
nils are suppressed from the output and do not appear in the joined string, and there are no commas around missing (nil) elements.
Related
I have an array:
scores = [1, 2, 3, "", 4]
And I want to remove all blank values. But when I run this:
puts scores.reject(&:empty?)
I get an error:
undefined method `empty' for 1:Fixnum
How can I remove values that are not integers from my array in a one step process? I am using Ruby 1.9.3.
To reject only nil would be:
array.compact
If you want to remove blank values, you should use blank?: (requires Rails / ActiveSupport)
scores.reject(&:blank?)
#=> [1, 2, 3, 4]
"", " ", false, nil, [], and {} are blank.
It is as simple as:
scores.grep(Integer)
Note that if you plan to map the values, you can do that in a block after:
scores.grep(Integer){|x| x+1 }
Bonus if you want to do the same thing, but your numbers are strings:
scores.grep(/\d+/){|x|x.to_i}
Try this :
scores.select{|e| e.is_a? Integer}
# => [1, 2, 3, 4]
If you really need reject nil only, so it can be done like this:
scores.reject(&:nil?)
scores = [1, 2, 3, "", 4, nil]
scores.reject{|s| s.to_s == ''}
# => [1, 2, 3, 4]
This Worked for me
scores.reject!{|x| x.to_s.empty?}
scores.select{|score| score.is_a? Fixnum}
or, as Fixnum inherits from Integer, you can also go for
scores.select{|score| score.is_a? Integer)
...if that seems more descriptive.
Array and Enumerable tend to offer many ways of doing the same thing.
&:empty? will work for hashes, arrays, and strings, but not numbers. The method you use in reject must be valid for all items in a list. &:blank? will work fine for this reason.
I have an array in my Rails 3.1 apps that has made by several objects:
[#<Hardware id: 10, brand_id: 5, model: "B4200", description: "Stampante OKI B4200", typology_id: 3, sub_typology_id: 10, created_at: nil, updated_at: nil>, #<Hardware id: 19, brand_id: 9, model: "JetLab", description: "JetLab - 600 ", typology_id: 5, sub_typology_id: nil, created_at: nil, updated_at: nil>]
and I want remove one object from this array. Using Rails console, I've tried to do something such as (try to remove first object):
array.pop=#<Hardware id: 10, brand_id: 5, model: "B4200", description: "Stampante OKI B4200", typology_id: 3, sub_typology_id: 10, created_at: nil, updated_at: nil>
but it doesn't work. How can I do this?
UPDATED: My goal isn't to pop last element on array, but a generic object (everywhere inside array) that I should find using mysql search query.
my_array = [ 1, 2, 3 ]
item = my_array.pop
puts item
# => 3
puts my_array
# => [ 1, 2 ]
You probably want to use the Array#delete function
an_array = [1,3,4]
an_array.delete(3)
# => 3
puts an_array
# => [1,4]
Check it out in the Ruby documentation:
http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-delete
Here's the code:
# a = Array.new(3, Array.new(3))
a = [[nil,nil,nil],[nil,nil,nil]]
a[0][0] = 1
a.each {|line| p line}
With the output:
[1, nil, nil]
[nil, nil, nil]
but using the commented line:
[1, nil, nil]
[1, nil, nil]
[1, nil, nil]
So why is that?
The commented line is assigning three of the same reference to the array, so a change to one array will propagate across the other references to it.
As for the 2 arrays vs 3, that's simply a matter of the first line specifying 3 as its first parameter and only specifying 2 array literals in the second line.
To create the nested arrays without having any shared references:
a = Array.new(3) {Array.new(3)}
When passed a block ({...} or do ... end), Array.new will call the block to obtain the value of each element of the array.
I'm working with Ripper sexp expressions, it looks like this:
[:program,
[[:class,
[:const_ref, [:#const, "A", [1, 6]]],
nil,
[:bodystmt,
[[:class,
[:const_ref, [:#const, "B", [1, 15]]],
nil,
[:bodystmt,
[[:def,
[:#ident, "test", [1, 22]],
[:params, nil, nil, nil, nil, nil],
[:bodystmt, [[:void_stmt]], nil, nil, nil]]],
nil,
nil,
nil]]],
nil,
nil,
nil]]]]
And i'm using array as path to get element in sexp expression. For example
path = [1,0,1,1] => sexp[1][0][1][1]
will get me
[:#const, "A", [1, 6]]
With this path I can get next, previous, parent elements and so on.
But I'm wondering is there a data structure which more suitable for this kind of tasks?
Besides the obvious trees, you may want to look at zippers:
http://en.wikipedia.org/wiki/Zipper_(data_structure)
Someone recently implemented form-zip for Clojure, if you want to look at an example:
https://github.com/GeorgeJahad/form-zip
This question already has answers here:
Value inside array having same object id [duplicate]
(2 answers)
Closed 11 months ago.
ruby 1.8.7 (2008-08-11 patchlevel 72) [i586-linux]
From script/console:
>> pairs = Array.new(2).map!{Array.new(2).map!{Array.new(2, Array.new)}}
=> [[[[], []], [[], []]], [[[], []], [[], []]]]
>> pair = Pair.first
=> #<Pair id: 39, charge_card_id: 1, classroom_id: 1, timeslot_id: 1, created_at: "2010-04-01 00:45:37", updated_at: "2010-04-01 00:45:47">
>> pairs[0][0][0] << pair
=> [#<Pair id: 39, charge_card_id: 1, classroom_id: 1, timeslot_id: 1, created_at: "2010-04-01 00:45:37", updated_at: "2010-04-01 00:45:47">]
>> pairs[0][0]
=> [[#<Pair id: 39, charge_card_id: 1, classroom_id: 1, timeslot_id: 1, created_at: "2010-04-01 00:45:37", updated_at: "2010-04-01 00:45:47">], [#<Pair id: 39, charge_card_id: 1, classroom_id: 1, timeslot_id: 1, created_at: "2010-04-01 00:45:37", updated_at: "2010-04-01 00:45:47">]]
>>
So the question is why the pair object appears in pairs[0][0][0] AND in pairs[0][0][1] inspite of I did'n ask it to appear there. Notice I don't nedd to pairs[0][0][0] = pair - I want it as a first array member, so I need to use << or .push.
First of all, you want
pairs = Array.new(2) { Array.new(2) { Array.new(2) { [] }}}
instead of what you got. Two major differences:
you save yourself the #map! calls
in your example, "Array.new(2, Array.new)" is creating one Array which is used for both indices, so you are refering to the same array twice. By using the block syntax, you are ensuring that for every index you are having one separate instance of Array
Now works with:
pairs = Array.new(2).map!{Array.new(2).map!{Array.new(2).map!{Array.new}}}
I think it's because of the deepest arrays was just links to memory pointer.
Array.new(2, Array.new) gives you an array of size 2, with a copy of the same empty array object at both index 0 and index 1. If you want them to be different objects, use map! like you've done at the higher levels.