I have a 4-dimensional NArray, and I'm overriding #each so that it only iterates over a single dimension, then using include Enumerable for functionality like #reject, #inject, etc. However, #sort still iterates over every individual element rather than over the dimension I've selected.
Is there a way to explicitly use Enumerable's #sort method, or do I have to write my own? I only have to call it once (so far), so it can be kind of weird or inconvenient.
NOTE: I realize that this question may seem like a duplicate. However, I do not want to ALWAYS override #sort, but rather just explicitly call Enumerable's #sort method.
If you call sort on the first level, whose elements are arrays, then sort will compare arrays. In order to compare arrays, the evaluation has to go inside those arrays, which means that it will be iterating over every level of array. It does not make sense to compare array elements while avoiding iterations into the sublevel. So if this is what you are trying to do, then there is no way.
NArray has already #sort method and existing methods are not overridden through include. In Ruby 2.0, you can use prepend instead of include.
Related
I found the following syntax in another question, and I have been unable to find any documentation on what its doing - I'm assuming syntactic sugar of some sort:
[array1, array2, array3, array4].compact.reduce([], :|)
I allows for one of the arrays to be nil instead of an array, and seems to work like a charm. Can anyone point me in the right direction to understand what is going on?
The original question is here: Merge arrays if not nil and not empty
It's a symbol, like :test, but a single character symbol.
The two-argument version of reduce accepts as a second argument a method name, the name of the method in this case is :|, or the | method. | on arrays is a set operation, it "or"s the arrays together, giving you the unique superset of all elements contained in both arrays. This isn't a particularly idiomatic use of reduce, you could achieve the same thing with .flatten.uniq
If you wanted to add the numbers, you could use :+, or to multiply you could use :*.
It's the same thing as this:
[array1, array2, array3, array4].compact.reduce([]) do |memo, array|
memo | array
end
Although it has syntactic sugar, Array#| is a method which you can see the docs for here. As the docs say:
Set Union — Returns a new array by joining ary with other_ary, excluding any duplicates and preserving the order from the original array
When the block of reduce takes this particular form (calling a single method on memo, passing the iteration's element as an argument), you can omit the block and just pass the method name.
Let's say,
i=2
#driver.find_elements("...").get(i).click
How to define similar method in ruby; any tweak on the same?
Use this code to click that link
get method is not available for array, you can take first element by first and last element by last and if you want any other elements you could use [i]
#driver.find_elements("...")[i].click
Let's say we have a Ruby method like this:
# Pseudocode
def get(globbed)
a_items = Dir.glob(globbed)
a_items.length == 1 ? a_items.first : a_items
end
The method is meant to return a String containing information about the items in question. If there are many items, it will return an Array. The ternary makes it so that if there is only one item, it just returns that String.
What is the best practice here? Should such a method always return an Array even if there is only one item?
It should always return an array. Returning different things means that whatever method that calls this method would also have to have a condition. That is not good. Whenever you can get rid of a condition, you should. A condition should only be used as a last resort.
As a real example, the jQuery library built on top of JavaScript has the notion of selectors, expressed in the form $(...). This can result in multiple matching dom objects, or a single one. But jQuery always returns an array even if the matched dom object is one. That makes things simple.
It's always about use cases. You have to define what's the responsibility of that method and then decide what makes sense to do.
In this specific case, I would say that, unless there isn't any specific reason to return different types, you should choose the way that is simpler, both to test and to read.
Always returning an array in this case means clearer method interface:
"The method returns an array with the directory content"
instead of the more convoluted
"The method returns an array of directory content if there more than
one object, otherwise return the single object."
So, clarity first of all.
And: testing would result easier. The cyclomatic complexity of the routine is less.
There are cases where the uniformity of return types can't be fulfilled. Just think of the Array method index: it wouldn't be possible to distinguish between "object not found" and "index 0" if the practice here was applied.
Conclusion: here I don't see any reason why to make the method more complex by distinguishing the two cases, so.. KISS.
Hi, ruby provides block, yield and iterator to permit easy array or hash treatment. And it's a good practice to use the same code for one or several numbers of element. Exemple :
a_items.each { |element| file_treatment(element) }
Regards.
I was going to comment on the original question but I don't have the reputation to do so yet....
I too was wondering how to easily update all the values in a hash, or if there was some kind of equivalent .map! method for hashes. Someone put up this elegant solution:
hash.update(hash){|key,v1| expresion}
on this question:
Ruby: What is the easiest method to update Hash values?
My questions is how does the block know to iterate over each element in the hash? For example, I'd have to call .each on a hash to access each element normally so why isn't it something like:
hash.update(hash.each) do |key ,value|
value+=1
end
In the block with {|key, value| expression} I am accessing each individual hash element yet I don't have to explicitly tell the system this? Why not? Thank you very much.
Hash#update is an alias for Hash#merge! which is more descriptive.
When calling the method with a block, the following happens (excerpt from the docs):
If [a] block is specified, [...] the value of each duplicate key is
determined by calling the block with the key [...]
So, the above code works like this:
The hash is merged with itself, and for each duplicate key the block is called. As we merge the hash with itself, every newly added key is a duplicate and therefore the block is invoked. The result is that every value in the hash gets replaced by expresion.
Hash#update takes a hash as the first parameter, and an optional block as the second parameter. If the second parameter is left out, the method will internally loop on each key-value pair in the supplied hash and use them to merge into the original hash.
If the block (second parameter) is supplied, the method does exactly the same thing. It loops over each key-value in the supplied hash and merges it in. The only difference is where a collision is found (the original hash already has an entry for a specific key). In this case the block is called to help resolve the conflict.
Based on this understanding, simply passing the hash into itself will cause it to loop over every key-value because that's how update always works. Calling .each would be redundant.
To see this more clearly, take a look at the source code for the #update method, and note the internal call to rb_hash_foreach in either logic branch.
The difference between Enumerable#each and Enumerable#map is whether it returns the receiver or the mapped result. Getting back to the receiver is trivial and you usually do not need to continue a method chain after each like each{...}.another_method (I probably have not seen such case. Even if you want to get back to the receiver, you can do that with tap). So I think all or most cases where Enumerable#each is used can be replaced by Enumerable#map. Am I wrong? If I am right, what is the purpose of each? Is map slower than each?
Edit:
I know that there is a common practice to use each when you are not interested in the return value. I am not interested in whether such practice exists, but am interested in whether such practice makes sense other than from the point of view of convention.
The difference between map and each is more important than whether one returns a new array and the other doesn't. The important difference is in how they communicate your intent.
When you use each, your code says "I'm doing something for each element." When you use map, your code says "I'm creating a new array by transforming each element."
So while you could use map in place of each, performance notwithstanding, the code would now be lying about its intent to anyone reading it.
The choice between map or each should be decided by the desired end result: a new array or no new array. The result of map can be huge and/or silly:
p ("aaaa".."zzzz").map{|word| puts word} #huge and useless array of nil's
I agree with what you said. Enumerable#each simply returns the original object it was called on while Enumerable#map sets the current element being iterated over to the return value of the block, and then returns a new object with those changes.
Since Enumerable#each simply returns the original object itself, it can be very well preferred over the map when it comes to cases where you need to simply iterate or traverse over elements.
In fact, Enumerable#each is a simple and universal way of doing a traditional iterating for loop, and each is much preferred over for loops in Ruby.
You can see the significant difference between map and each when you're composing these enumaratiors.
For example you need to get new array with indixes in it:
array.each.with_index.map { |index, element| [index, element] }
Or for example you just need to apply some method to all elements in array and print result without changing the original array:
m = 2.method(:+)
[1,2,3].each { |a| puts m.call(a) } #=> prints 3, 4, 5
And there's a plenty another examples where the difference between each and map is important key in the writing code in functional style.