to_s method is not displaying the right result - ruby

I have an array: [1, "2", 3.0, ["a", "b"], "dog"]
typing array.to_s in my command prompt gives me this:
[1, \"2\", 3.0, [\"a\", \"b\"], \"dog\"]
Which is wrong, and it is suppose to give me this:
123.0abdog
Would someone explain to me why I'm not getting the right result?

You, probably, want to join array:
[1, "2", 3.0, ["a", "b"], "dog"].join
=> "123.0abdog"
to_s works differently, according to the docs, it creates a string representation of an array:
[ "a", "b", "c" ].to_s #=> "[\"a\", \"b\", \"c\"]"

What it's giving you is the correct result. .to_s only ever returns a string representation of the object you call it on. In this case, it returns what the array looks like when represented as a string. This doesn't just mean flattening and combining all the elements into a string and is not generally intended to mean such.
If you want to run some code to get that result, try:
[1, "2", 3.0, ["a", "b"], "dog"].flatten.join

You first need to get rid of the nested array bby using flatten. Then you can join it into a string.
[1, "2", 3.0, ["a", "b"], "dog"].flatten.join

Related

Ruby - how to pop a specific element from an array

What would be the easiest way in Ruby to pop a specific element from an array, similar to the .delete method of
a.delete(element)
rather than popping the first/last element or using .slice?
To make this more specific: for example, I can do
case names.sample when "John", "Dave", "Sam"
a.delete(names.sample)
end
to delete one of those names from a when it appears as a sample from names
However, I intend to use multiple samples and using a.delete()will remove all elements at once, rather than in succession like the result produced from shuffle!.pop where elements are popped in succession, so that the name can no longer be selected as a sample from a after the same name has been selected as a name.sample
I was wondering what the easiest way would be in Ruby to pop off these elements in succession, or if it is even possible at all in this context.
The Array class defines a pop method. It returns and deletes the last element in the array.
a = ["a", "b", "c"]
puts a.pop #=> "c"
puts a #=> ["a", "b"]
You can optionally pass an argument to pop that specifies how many elements to pop off.
a = ["a", "b", "c"]
puts a.pop(2) #=> ["b", "c"]
puts a #=> ["a"]
Addressing your last comment, you can use include?, index, and delete_at methods to achieve this. Assuming you're checking for "b" in an array:
a = ["a", "b", "c"]
value_index = a.index("b") #Returns the first occurring index of "b"
has_value = a.include?("b") #Returns whether "b" is in the list
a.delete_at(a.index("b")) if has_value #Removes "b" from the list
In this sample, "has_value" will be whether the a array contains the value "b", and "value_index" will be the first occurrence of "b". This will also delete the value "b" from the list.
If you want to remove all occurrences of "b", you can use include?, index, and delete_at with a while loop:
a = ["a", "b", "c", "a", "b", "c"]
while a.include?("b")
a.delete_at(a.index("b"))
end
#a will now be ["a", "c", "a", "c"]
See also the documentation for Array.
[..] intend to use multiple samples and using a.delete() will remove all elements at once, rather than in succession like the result produced from shuffle!.pop where elements are popped in succession, so that the name can no longer be selected as a sample from a after the same name has been selected as a name.sample[..]
Maybe you are looking something like this?
names = ["John", "Dave", "Sam"]
names.size.times { p names.delete(names.sample) }
#=> "Sam"
#=> "John"
#=> "Dave"

How to extract each individual combination from a flat_map?

I'm fairly new to ruby and it's my first question here on stackoverflow so pardon me if I'm being a complete noob.
The code which i am working with contains this line -
puts (6..6).flat_map{|n| ('a'..'z').to_a.combination(n).map(&:join)}
What the code does is that its starts printing each of the combinations starting from "abcdef" and continues till the end (which i have never seen as it has 26^6 combinations).
Of course having an array of that size (26^6) is unimaginable hence I was wondering if there is any way by which i can get next combination in a variable, work with it, and then continue on to the next combination ?
For example I calculate the first combination as "abcdef" and store it in a variable 'combo' and use that variable somewhere and then the next combination is calculated and "abcdeg" is stored in 'combo' and hence the loop continues ?
Thanks
(6..6).flat_map { |n| ... } doesn't do much. Your code is equivalent to:
puts ('a'..'z').to_a.combination(6).map(&:join)
To process the values one by one, you can pass a block to combination:
('a'..'z').to_a.combination(6) do |combo|
puts combo.join
end
If no block is given, combination returns an Enumerator that can be iterated by calling next:
enum = ('a'..'z').to_a.combination(6)
#=> #<Enumerator: ["a", "b", "c", ..., "w", "x", "y", "z"]:combination(6)>
enum.next
#=> ["a", "b", "c", "d", "e", "f"]
enum.next
#=> ["a", "b", "c", "d", "e", "g"]
enum.next
#=> ["a", "b", "c", "d", "e", "h"]
Note that ('a'..'z').to_a.combination(6) will "only" yield 230,230 combinations:
('a'..'z').to_a.combination(6).size
#=> 230230
As opposed to 26 ^ 6 = 308,915,776. You are probably looking for repeated_permutation:
('a'..'z').to_a.repeated_permutation(6).size
#=> 308915776
Another way to iterate from "aaaaaa" to "zzzzzz" is a simple range:
('aaaaaa'..'zzzzzz').each do |combo|
puts combo
end
Or manually by calling String#succ: (this is what Range#each does under the hood)
'aaaaaa'.succ #=> "aaaaab"
'aaaaab'.succ #=> "aaaaac"
'aaaaaz'.succ #=> "aaaaba"

Splitting a string into an array ruby

I am trying to turn this string
"a,bc,c"
into this array..
["a", "b", "c"]
I've used split on the comma & iterated through it but I'd like to find a cleaner way.
Thanks!
I will use #scan and #uniq method.
"a, bc,c".scan(/[a-z]/).uniq
# => ["a", "b", "c"]
Here we go, one option:
"a, bc,c".gsub(/\W+/, '').chars.uniq
# Outputs:
=> ["a", "b", "c"]

How to programmatically fetch ruby documentation of corelib / stdlib?

I have a big array. This array has all of ruby stdlib in like this format:
Array#size
Array#push
String#replace
String#<<
And so on. Now I wish to find the corresponding documentation of that method
and give it back to the user. (It is like a cheap REPL, a mini irb if you
so will - and I only need this mini functionality, nothing fully fledged.)
How could I find the part where Array#push is documented?
I am fine using rdoc/yard/ri, I only need to get the
docu from there in a string-form.
You can dig down into the RDoc documentation and access the Rdoc::RI::Driver code that ri uses, then play some games with how it outputs the data to capture what would normally go to the screen by using a StringIO object:
require 'rdoc'
require 'stringio'
ri = RDoc::RI::Driver.new(RDoc::RI::Driver.process_args(%w[-T --format=ansi ]))
ri.use_stdout = true
ri_output = ''
$stdout = StringIO.new(ri_output)
ri.display_method('Array#push')
$stdout = STDOUT
puts ri_output
Which results in:
[0m[1;32mArray#push[m
(from ruby core)
------------------------------------------------------------------------------
ary.push(obj, ... ) -> ary
------------------------------------------------------------------------------
Append --- Pushes the given object(s) on to the end of this array. This
expression returns the array itself, so several appends may be chained
together. See also Array#pop for the opposite effect.
a = [ "a", "b", "c" ]
a.push("d", "e", "f")
#=> ["a", "b", "c", "d", "e", "f"]
[1, 2, 3,].push(4).push(5)
#=> [1, 2, 3, 4, 5]
Change the output type to markdown to get output that doesn't use the ANSI terminal display codes:
ri = RDoc::RI::Driver.new(RDoc::RI::Driver.process_args(%w[-T --format=markdown ]))
Which results in:
# Array#push
(from ruby core)
---
ary.push(obj, ... ) -> ary
---
Append --- Pushes the given object(s) on to the end of this array. This
expression returns the array itself, so several appends may be chained
together. See also Array#pop for the opposite effect.
a = [ "a", "b", "c" ]
a.push("d", "e", "f")
#=> ["a", "b", "c", "d", "e", "f"]
[1, 2, 3,].push(4).push(5)
#=> [1, 2, 3, 4, 5]
This little piece of magic allows us to capture the normal output that would go to STDOUT on the console into a string:
ri_output = ''
$stdout = StringIO.new(ri_output)
At that point, all normal STDOUT-based output will be stored in ri_output and not go to the console. Following that it's important to reassign STDOUT back to $stdout so puts output goes to the console again:
$stdout = STDOUT
It's probably possible to intercept the output prior to it going to the normal ri console output, but I didn't see a method, or way, for doing that that stood out.
I would use ri with a system call. For example
`ri Array#push`
returns
= Array#push
(from ruby core)
------------------------------------------------------------------------------
ary.push(obj, ... ) -> ary
------------------------------------------------------------------------------
Append --- Pushes the given object(s) on to the end of this array. This
expression returns the array itself, so several appends may be chained
together. See also Array#pop for the opposite effect.
a = [ "a", "b", "c" ]
a.push("d", "e", "f")
#=> ["a", "b", "c", "d", "e", "f"]
[1, 2, 3,].push(4).push(5)
#=> [1, 2, 3, 4, 5]

How might I match a string in ruby without using regular expressions?

Currently, I'm doing this:
(in initialize)
#all = Stuff.all.each.map {|t| t.reference_date }
#uniques = #all.uniq
results = []
#uniques.each do |k|
i = 0
#all.each do |x|
i += 1 if x =~ %r{#{x}}
end
results << [k, i]
end
And that's fine. It's going to work. But I like to avoid regular expressions when I can. I think they are a bit feo. That's spanish for ugly.
EDIT--
actually, that's not working because ruby "puts" the date as a numbered format like 2012-03-31 when the date object is placed inside of a string (as a variable, here), but its really a date object, so this worked:
if x.month == k.month && x.day == k.day
i += 1
end
You can do it with just 1 line (if I got right the question of course):
array = %w(a b c d a b d f t z z w w)
# => ["a", "b", "c", "d", "a", "b", "d", "f", "t", "z", "z", "w", "w"]
array.uniq.map{|i|[i, array.count(i)]}
# => [["a", 2], ["b", 2], ["c", 1], ["d", 2], ["f", 1], ["t", 1], ["z", 2], ["w", 2]]
results = Hash.new(0)
#all.each{|t| results[t] += 1}
# stop here if a hash is good enough.
# if you want a nested array:
results = results.to_a
This is the standard way of getting the frequency of elements in an enumerable.
Something you can do to avoid the appearance of regular expressions, is to build them on the fly using Regexp.union. The reason you might want to do this is SPEED. A well constructed regex is faster than iterating over a list, especially a big one. And, by allowing your code to build the regex, you don't have to maintain some ugly (feo) thing.
For instance, here's something I do in different chunks of code:
words = %w[peer_address peer_port ssl ssl_protocol ssl_key_exchange ssl_cipher]
regex = /\b(?:#{ Regexp.union(words).source })\b/i
=> /\b(?:peer_address|peer_port|ssl|ssl_protocol|ssl_key_exchange|ssl_cipher)\b/i
That makes it trivial to maintain a regex. And, try a benchmark using that to find substrings in text against iterating and it'll impress you.
If wildcards will work for you, try File.fnmatch
From your code I sense you want to get the number of occurrence of each reference_date. This can be achieved much easier by using ActiveRecord and SQL directly instead of pulling the whole tale and then performing time consuming operations in Ruby.
If you are using Rails 2.x you can use something like this:
Stuff.find(:all, :select => "reference_date, COUNT(*)", :group => "reference_date")
or if you are using Rails 3 then you can simplify it to
Stuff.count(:group => "reference_date")

Resources