Convert integer string to array of integers

I did use the below :-

"12\^ abc23 44".scan(/\d+/).map(&:to_i)
# => [12, 23, 44]

Now, I thought, let's try to do this without creating an intermediate array.

Then I saw, String#scan supports block, so I can write

ar = []
"12\^ abc23 44".scan(/\d+/) { |e| ar << e.to_i }

Then I thought, lets use the *block support* of `#scan` some other way and I
came up with the below :-

"12\^ abc23 44".enum_for(:scan, /\d+/).with_object([]) { |e, a| a << e.to_i }
# => [12, 23, 44]

It works, but not I am able to understand, if it is creating the intermediate
array ( as #scan do without block), or block version of #scan is getting
called.

···

--

Regards,
Arup Rakshit

Debugging is twice as hard as writing the code in the first place. Therefore,
if you write the code as cleverly as possible, you are, by definition, not
smart enough to debug it.

--Brian Kernighan

Does it matter that much? BTW if all you care about is only creating a
single array, you could use #map!

···

On 5 July 2014 17:52, Arup Rakshit <aruprakshit@rocketmail.com> wrote:

I did use the below :-

"12\^ abc23 44".scan(/\d+/).map(&:to_i)
# => [12, 23, 44]

Now, I thought, let's try to do this without creating an intermediate
array.

Then I saw, String#scan supports block, so I can write

ar =
​​
"12\^ abc23 44".scan(/\d+/) { |e| ar << e.to_i }

Then I thought, lets use the *block support* of `#scan` some other way and
I
came up with the below :-

"12\^ abc23 44".enum_for(:scan, /\d+/).with_object() { |e, a| a <<
e.to_i }
# => [12, 23, 44]

It works, but not I am able to understand, if it is creating the
intermediate
array ( as #scan do without block), or block version of #scan is getting
called.

--
  Matthew Kerwin
  http://matthew.kerwin.net.au/

> It works, but not I am able to understand, if it is creating the
> intermediate
> array ( as #scan do without block), or block version of #scan is getting
> called.

Does it matter that much?

Curiosity ... :slight_smile:

BTW if all you care about is only creating a
single array, you could use #map!

Yes latter I found it, which shorten the length of code. :slight_smile: But curiosity
remains still there inside the `#enum_for` construct...

···

On Saturday, July 05, 2014 07:52:31 PM Matthew Kerwin wrote:

--

Regards,
Arup Rakshit

Debugging is twice as hard as writing the code in the first place. Therefore,
if you write the code as cleverly as possible, you are, by definition, not
smart enough to debug it.

--Brian Kernighan

And what do you want to know?

Cheers

robert

···

On Sat, Jul 5, 2014 at 2:38 PM, Arup Rakshit <aruprakshit@rocketmail.com> wrote:

Yes latter I found it, which shorten the length of code. :slight_smile: But curiosity
remains still there inside the `#enum_for` construct...

--
[guy, jim].each {|him| remember.him do |as, often| as.you_can - without end}
http://blog.rubybestpractices.com/

Robert,

I want to know in the below code :-

"12\^ abc23 44".enum_for(:scan, /\d+/).with_object() { |e, a| a << e.to_i }
#or
"12\^ abc23 44".enum_for(:scan, /\d+/).map { |e, a| a << e.to_i }

*e* is coming from -

"12\^ abc23 44".scan(/\d+/) { |e| e } # from block version ?
#or
"12\^ abc23 44".scan(/\d+/) # produces array. From this array ?

Hope I am now able to express my curiosity. :slight_smile:

···

On Saturday, July 05, 2014 09:37:00 PM Robert Klemme wrote:

On Sat, Jul 5, 2014 at 2:38 PM, Arup Rakshit <aruprakshit@rocketmail.com> wrote:
> Yes latter I found it, which shorten the length of code. :slight_smile: But curiosity
> remains still there inside the `#enum_for` construct...

And what do you want to know?

Cheers

robert

--

Regards,
Arup Rakshit

Debugging is twice as hard as writing the code in the first place. Therefore,
if you write the code as cleverly as possible, you are, by definition, not
smart enough to debug it.

--Brian Kernighan

sorry for wrong copy paste :-

"12\^ abc23 44".enum_for(:scan, /\d+/).map { |e| e.to_i }

···

On Sunday, July 06, 2014 12:14:37 PM Arup Rakshit wrote:

On Saturday, July 05, 2014 09:37:00 PM Robert Klemme wrote:
> On Sat, Jul 5, 2014 at 2:38 PM, Arup Rakshit <aruprakshit@rocketmail.com>

I want to know in the below code :-

"12\^ abc23 44".enum_for(:scan, /\d+/).with_object() { |e, a| a << e.to_i
} #or
"12\^ abc23 44".enum_for(:scan, /\d+/).map { |e, a| a << e.to_i }

--

Regards,
Arup Rakshit

Debugging is twice as hard as writing the code in the first place. Therefore,
if you write the code as cleverly as possible, you are, by definition, not
smart enough to debug it.

--Brian Kernighan

Hi Arup,

Sorry if I misunderstood your question, but I'll try to help.

"12\^ abc23 44".scan(/\d+/) { |e| e }
# It iterates through each element and then returns the 'source' String!

So if you run the line you have pasted, you just receive back the
string you've given.
But it truly has iterated through all matches.
To see it, change

"12\^ abc23 44".scan(/\d+/) { |e| e }
to
"12\^ abc23 44".scan(/\d+/) { |e| puts e }

And you're gonna see it outputting:
12
23
44
# And then returns => "12^ abc23 44"

If you use map (alias for collect) it collects/maps those values.

So,

"12\^ abc23 44".scan(/\d+/)
"12\^ abc23 44".scan(/\d+/).map { |e| e }

Was it related to your question? Did it help you?

···

On Sun, Jul 6, 2014 at 2:55 AM, Arup Rakshit <aruprakshit@rocketmail.com> wrote:

On Sunday, July 06, 2014 12:14:37 PM Arup Rakshit wrote:

On Saturday, July 05, 2014 09:37:00 PM Robert Klemme wrote:
> On Sat, Jul 5, 2014 at 2:38 PM, Arup Rakshit <aruprakshit@rocketmail.com>

I want to know in the below code :-

"12\^ abc23 44".enum_for(:scan, /\d+/).with_object() { |e, a| a << e.to_i
} #or
"12\^ abc23 44".enum_for(:scan, /\d+/).map { |e, a| a << e.to_i }

sorry for wrong copy paste :-

"12\^ abc23 44".enum_for(:scan, /\d+/).map { |e| e.to_i }

--

Regards,
Arup Rakshit

Debugging is twice as hard as writing the code in the first place. Therefore,
if you write the code as cleverly as possible, you are, by definition, not
smart enough to debug it.

--Brian Kernighan

Continuation...

So,

"12\^ abc23 44".scan(/\d+/)
"12\^ abc23 44".scan(/\d+/).map { |e| e }
"12\^ abc23 44".enum_for(:scan, /\d+/).map { |e| e }
"12\^ abc23 44".enum_for(:scan, /\d+/).map.to_a
"12\^ abc23 44".enum_for(:scan, /\d+/).enum_for(:map).to_a

... are pretty equivalent (in results term) and you should use the
first form, and I see no reason for using the laters apart from
"learning" and understanding enumerators.

Abinoam Jr.

···

On Sun, Jul 6, 2014 at 8:34 AM, Abinoam Jr. <abinoam@gmail.com> wrote:

Hi Arup,

Sorry if I misunderstood your question, but I'll try to help.

"12\^ abc23 44".scan(/\d+/) { |e| e }
# It iterates through each element and then returns the 'source' String!

So if you run the line you have pasted, you just receive back the
string you've given.
But it truly has iterated through all matches.
To see it, change

"12\^ abc23 44".scan(/\d+/) { |e| e }
to
"12\^ abc23 44".scan(/\d+/) { |e| puts e }

And you're gonna see it outputting:
12
23
44
# And then returns => "12^ abc23 44"

If you use map (alias for collect) it collects/maps those values.

So,

"12\^ abc23 44".scan(/\d+/)
"12\^ abc23 44".scan(/\d+/).map { |e| e }

Was it related to your question? Did it help you?

On Sun, Jul 6, 2014 at 2:55 AM, Arup Rakshit <aruprakshit@rocketmail.com> wrote:

On Sunday, July 06, 2014 12:14:37 PM Arup Rakshit wrote:

On Saturday, July 05, 2014 09:37:00 PM Robert Klemme wrote:
> On Sat, Jul 5, 2014 at 2:38 PM, Arup Rakshit <aruprakshit@rocketmail.com>

I want to know in the below code :-

"12\^ abc23 44".enum_for(:scan, /\d+/).with_object() { |e, a| a << e.to_i
} #or
"12\^ abc23 44".enum_for(:scan, /\d+/).map { |e, a| a << e.to_i }

sorry for wrong copy paste :-

"12\^ abc23 44".enum_for(:scan, /\d+/).map { |e| e.to_i }

--

Regards,
Arup Rakshit

Debugging is twice as hard as writing the code in the first place. Therefore,
if you write the code as cleverly as possible, you are, by definition, not
smart enough to debug it.

--Brian Kernighan

Continuation...

So,

"12\^ abc23 44".scan(/\d+/)
"12\^ abc23 44".scan(/\d+/).map { |e| e }
"12\^ abc23 44".enum_for(:scan, /\d+/).map { |e| e }
"12\^ abc23 44".enum_for(:scan, /\d+/).map.to_a
"12\^ abc23 44".enum_for(:scan, /\d+/).enum_for(:map).to_a

... are pretty equivalent (in results term) and you should use the
first form,

Thanks for your details explanation.

apart from
"learning" and understanding enumerators.

Your catch is correct, Just to understand and learning.

It seems I am not able to clear myself to you people. I know how #scan works.
But question is while I am writing

"any string".enum_for(:scan, /\d+/) --- then which version of block is
actually called, *block version* or *without block* version. Because I am not
able to see it,

If I write "any string".scan(/\d+/) --- It is clear that I am using without
block version.

Now If I write "any string".scan(/\d+/) { |m| p m } - It is clear I am using
block version.

Now, while I write - "any string".enum_for(:scan, /\d+/) -- I can't see how
$scan is actually working. So my question came out right there...

Hope it is clear now.

···

On Sunday, July 06, 2014 08:41:34 AM Abinoam Jr. wrote:

--

Regards,
Arup Rakshit

Debugging is twice as hard as writing the code in the first place. Therefore,
if you write the code as cleverly as possible, you are, by definition, not
smart enough to debug it.

--Brian Kernighan

Continuation...

So,

"12\^ abc23 44".scan(/\d+/)
"12\^ abc23 44".scan(/\d+/).map { |e| e }
"12\^ abc23 44".enum_for(:scan, /\d+/).map { |e| e }
"12\^ abc23 44".enum_for(:scan, /\d+/).map.to_a
"12\^ abc23 44".enum_for(:scan, /\d+/).enum_for(:map).to_a

... are pretty equivalent (in results term) and you should use the
first form,

Thanks for your details explanation.

apart from
"learning" and understanding enumerators.

Your catch is correct, Just to understand and learning.

It seems I am not able to clear myself to you people. I know how #scan works.
But question is while I am writing

"any string".enum_for(:scan, /\d+/) --- then which version of block is
actually called, *block version* or *without block* version. Because I am not
able to see it,

If I write "any string".scan(/\d+/) --- It is clear that I am using without
block version.

Now If I write "any string".scan(/\d+/) { |m| p m } - It is clear I am using
block version.

Now, while I write - "any string".enum_for(:scan, /\d+/) -- I can't see how
$scan is actually working. So my question came out right there...

Hope it is clear now.

One way I have started to understand how Ruby's interpreter works is to look at the source. These days I use pry to look at things in Ruby as I can use pry's $ command to see source:

[1]pry(main)> $ String#scan

Owner: String
Visibility: public
Number of lines: 30

static VALUE
rb_str_scan(VALUE str, VALUE pat)
{
    VALUE result;
    long start = 0;
    long last = -1, prev = 0;
    char *p = RSTRING_PTR(str); long len = RSTRING_LEN(str);

    pat = get_pat(pat, 1);
    if (!rb_block_given_p()) {
        VALUE ary = rb_ary_new();

        while (!NIL_P(result = scan_once(str, pat, &start))) {
            last = prev;
            prev = start;
            rb_ary_push(ary, result);
        }
        if (last >= 0) rb_reg_search(pat, str, last, 0);
        return ary;
    }

    while (!NIL_P(result = scan_once(str, pat, &start))) {
        last = prev;
        prev = start;
        rb_yield(result);
        str_mod_check(str, p, len);
    }
    if (last >= 0) rb_reg_search(pat, str, last, 0);
    return str;
}

There aren't two different versions of String#scan, when a String is sent the scan message the scan method checks to see if it was given a block. If no block was given then it builds and returns a new array, populates it and returns it. If there was a block given then it yields the results as it finds them and eventually returns the original string.

Another fun place to look for implementations of bits of Ruby is in Rubinius, as most of it is written in Ruby.

Hope this helps,

Mike

···

On Jul 6, 2014, at 7:27 AM, Arup Rakshit <aruprakshit@rocketmail.com> wrote:

On Sunday, July 06, 2014 08:41:34 AM Abinoam Jr. wrote:

From: string.c (C Method):

--

Mike Stok <mike@stok.ca>
http://www.stok.ca/~mike/

The "`Stok' disclaimers" apply.

Continuation...

So,

"12\^ abc23 44".scan(/\d+/)
"12\^ abc23 44".scan(/\d+/).map { |e| e }
"12\^ abc23 44".enum_for(:scan, /\d+/).map { |e| e }
"12\^ abc23 44".enum_for(:scan, /\d+/).map.to_a
"12\^ abc23 44".enum_for(:scan, /\d+/).enum_for(:map).to_a

... are pretty equivalent (in results term) and you should use the
first form,

There are use cases for #enum_for though - these are typically related
to situations where the set of items generated may be large. Note
also that many methods implicitly do #enum_for if no block is passed,
e.g. Integer#times does this:

irb(main):008:0> x = 5.times
=> #<Enumerator: 5:times>
irb(main):009:0> x.class
=> Enumerator
irb(main):010:0> x.class.ancestors
=> [Enumerator, Enumerable, Object, Kernel, BasicObject]
irb(main):011:0> x.each {|i| p i}
0
1
2
3
4
=> 5

It seems I am not able to clear myself to you people. I know how #scan works.
But question is while I am writing

"any string".enum_for(:scan, /\d+/) --- then which version of block is
actually called, *block version* or *without block* version. Because I am not
able to see it,

If I write "any string".scan(/\d+/) --- It is clear that I am using without
block version.

Now If I write "any string".scan(/\d+/) { |m| p m } - It is clear I am using
block version.

Now, while I write - "any string".enum_for(:scan, /\d+/) -- I can't see how
$scan is actually working. So my question came out right there...

Hope it is clear now.

Yes. And you can test this yourself fairly easily:

irb(main):001:0> class X; def a; printf "block: %s\n", block_given? end end
=> nil
irb(main):002:0> X.new.enum_for(:a).each {|x| p x}
block: true
=> nil

If the method actually invokes the block this is what happens:

irb(main):003:0> class X; def a; printf "block: %s\n", block_given?;
yield 123 if block_given? end end
=> nil
irb(main):004:0> X.new.enum_for(:a).each {|x| p x}
block: true
123
=> 123

Kind regards

robert

···

On Sun, Jul 6, 2014 at 1:27 PM, Arup Rakshit <aruprakshit@rocketmail.com> wrote:

On Sunday, July 06, 2014 08:41:34 AM Abinoam Jr. wrote:

--
[guy, jim].each {|him| remember.him do |as, often| as.you_can - without end}
http://blog.rubybestpractices.com/