Why does each_slice with block and .map return nil
Asked Answered
E

1

9

Why does this return nil and what does line 2 mean? The array represents rows of a Sudoku puzzle which I'm trying to create a solution for.

I'm trying different methods in irb to see how many different ways I can view the array.

array = ['015003002000100906270068430490002017501040380003905000900081040860070025037204600']
array.each_slice(9) { |e| puts e.map }
#<Enumerator:0x0000010288a470>
=> nil
Ennui answered 28/1, 2014 at 21:7 Comment(1)
Your array has only one item ?Contemporary
P
15

Some methods expect a block, and if block is not provided, they return Enumerable.

In your example, you invoked map without providing any block.

But you can call enumerable methods on enumerators. This allows you to change the behaviour of the iterators.

array[0].split('').each_slice(9).map { |el| el }

=> [["0", "1", "5", "0", "0", "3", "0", "0", "2"],
 ["0", "0", "0", "1", "0", "0", "9", "0", "6"],
 ["2", "7", "0", "0", "6", "8", "4", "3", "0"],
 ["4", "9", "0", "0", "0", "2", "0", "1", "7"],
 ["5", "0", "1", "0", "4", "0", "3", "8", "0"],
 ["0", "0", "3", "9", "0", "5", "0", "0", "0"],
 ["9", "0", "0", "0", "8", "1", "0", "4", "0"],
 ["8", "6", "0", "0", "7", "0", "0", "2", "5"],
 ["0", "3", "7", "2", "0", "4", "6", "0", "0"]]

It's one of slightly more advanced topics in Ruby but there are lot of resources in the internet, f.i. http://www.sitepoint.com/guide-ruby-collections-iii-enumerable-enumerator/

EDIT:

Just to answer the questions in the comment: You have only one long string in array. I don't ask why, but just to make some example, I needed actual array of (string?) numbers. array[0] takes this first element in array (the long string of numbers). When I have a string I can call String#split to get an array like `["0", "1", "5", "..."].

Array includes Enumerable module, thanks to that you can call methods like each_slice on it. As the docs state (http://rubydoc.info/stdlib/core/Enumerable:each_slice):

If no block is given, returns an enumerator

So after calling each_slice(9) I get Enumerator instance (http://rubydoc.info/stdlib/core/Enumerator). It has some own methods, but also includes Enumerable module (with methods like map, each_slice. Here's where the fun begins. If I call any of those methods on our enumerator (like map), it won't receive each element of array, like in normal case, but each element "returned" by enumerator, i.e. each single element is now array of 9 elements.

As always I highly recommend the Well Grounded Rubyist, where such subjects are thoroughly explained. http://www.manning.com/black2/

Pontifical answered 28/1, 2014 at 21:10 Comment(3)
Thanks.So split takes each number in the array and turn it into it's own string, each_slice then iterates over the split array and then creates 9 array with 9 elements in each one? Sorry, confused. Does map using the block slice the split array 9 times? What's the [0] doing after array?Ennui
Ruby 2.2.0 which introduced Kernel#itself so you can do array[0].split('').each_slice(9).map(&:itself) which is a little clearer IMHO.Locular
just use .to_a on EnumeratorBorrell

© 2022 - 2024 — McMap. All rights reserved.