select method on array providing different results - arrays

The following are identical:
First method:
puts [1,2,3,4,5,6,6,6,6].select {|number| number == 6 }
Output:
6
6
6
6
Second method:
array = [1,2,3,4,5,6,6,6,6]
array.select do |number|
puts number == 6
end
Output:
false
false
false
false
false
true
true
true
true
Why don't I get the same result for each? How do I go about getting the same result? Please explain what is going on.

Described in the ruby doc,
select → an_enumerator
Returns an array containing all elements of enum for which the given
block returns a true value.
[1,2,3,4,5,6,6,6,6].select {|number| number == 6 }
returns as intended (i.e, return an array where the number == 6)
[6, 6, 6, 6]
In the second method, you're simply outputting the result of the comparison, which will result in a boolean.

Regarding the output, the first method puts the selected array whereas the second method puts each evaluation of the condition (regardless of whether the condition is met).
Regarding the selected array, the block in the first method returns the evaluation of number == 6, which leads to the selected array [6, 6, 6, 6], whereas the block in the second method returns the evaluation of puts, which is nil, which leads to the selected array [].
Regarding the return value of the entire code, the first method returns the evaluation of puts, which is nil, whereas the second method returns the selected array [].

Related

Comparing two array values and deleting row if condition is fullfilled

I have an array with 2 columns. I want to compare the values of the first column, like this:
a[i+1]-a[i]<0.0025.
If this is true I need to delete the row with a[i+1].
This is my first attempt, but it doesnt work.
a = np.delete(a, np.diff(a[:,0])<0.0025, 0)
I get the following error:
ValueError: boolean array argument obj to delete must be one dimensional and match the axis length of 8628
8628 is the length of the array.
Another code i´ve tried is:
a = a[~(np.diff(a[:,0]))<0.0025]
But then I get this error:
TypeError: ufunc 'invert' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
Can somebody help me with this?
You're on the right track. np.diff(a[:, 0]) < 0.0025 creates an array of length 1 less than 8628, which means when you use it in np.delete that the dimension no longer matches with the original array.
I would go with your second attempt. Using < 0.0025 results in a mask of items that you want to delete, which you need to invert using ~ to get a mask of results you would like to keep. You have to make sure to place your parentheses correctly: ~( np.diff(a[:, 0]) < 0.0025 ). Instead, you can also use >= 0.0025 to make a mask of items you would like to keep.
Lastly, you have to make sure to match the dimensions (given that np.diff results in one less element. You can do this by prepending True to signify that you always want to keep the first value. One way to do that is using np.r_.
Final code:
import numpy as np
a = np.random.rand(8628, 2) # Your array here
result = a[ np.r_[True, np.diff(a[:, 0]) >= 0.0025] ]
Detailed example:
Consider the array: [ 1, 3, 2, 5, 3]
np.diff creates: [ 2, -1, 3, -2]
Using threshold creates: [True, False, True, False]
Note that when the next element in the original array is less than the previous,
the thresholding result in False too.
Finally, because there are now 4 values instead of 5, we prepend True.
This has the effect of always including the first element in the result:
Original: [ 1, 3, 2, 5, 3]
Mask [True, True, False, True, False]
^^^^ ~~~~ ~~~~~ ~~~~ ~~~~~
Then using boolean indexing, we get the elements where
the mask contains True to obtain the final result:
[1, 3, 5]

Rails- is there a method that is essentially `map.find` for arrays?

Looking for a method that will iterate through a list and return the first transformed value.
Essentially:
[1, 2, 3, 4].magic { |i|
puts "Checking #{i}"
i ** 2 if i > 2
}
Checking 1
Checking 2
Checking 3
#=> 9
The goal here being that it works like find and stops iterating through the list after getting the first return. (Notice it never checks 4) but also returns the value from the block. (Returns 9 instead of 3)
The issue here is that the block is performing some complex logic, so I don't want to map over the entire array, but I also want to use the value of said logic.
You can break the loop with a desired return value. Is this what you are looking for?
array = [1, 2, 3, 4]
array.map { |element| break element ** 2 if element > 2 }
# returns 9

None in python array

arr=[1,2,3,4,5]
n=len(arr)
temp = n*[None]
flag = True
flag= bool(1-flag)
I'm new to python, so not sure what it really means.
I want to know what all three lines of code do. Thank you
The first line will create an array of five elements
print (arr)
[1, 2, 3, 4, 5]
The second will make a variable named 'n' that will contain the number of elements in your array
print(n)
5
The third line will create an array with a length of 5 that will only contain None.
None is used to define a variable so that it resets to a variable with no value. It is not similar to a NULL or an empty string, None is an object.
print(temp)
[None, None, None, None, None]
The last line will change your flag value to false.
In standard binary conventions, True is equal to 1 and False is equal to 0. By subtracting a 1 with the flag value that is True, you are doing 1-1 which is equal to Zero. With bool(), you obtain a false.
print(flag)
False

Looking at a hash as an array?

I found this example of using #any? on a hash a bit tricky:
"With a Hash, you can use these in two ways. Either with one argument that is a 2 element array of the key-value pair. candidate[0] is the key and candidate[1] is its value.
{:locke => 4, :hugo => 8}.any? { |candidate| candidate[1] > 4 }
This returns true because the value of the second candidate :hugo is greater than 4."
Could anyone point me someplace that explains what happened here? I couldn't find a relevant question on SO. Thanks a lot in advance.
If you print candidate it will become easy to understand:
{:locke => 4, :hugo => 8}.any? { |candidate| puts candidate.to_s }
# [:locke, 4]
# [:hugo, 8]
The any? method is treating each key-value pair of the hash as an a two-element array, which means the hash will be treated as an array of arrays.
The block passed to any? (i.e., { |candidate| candidate[1] > 4 }) returns true if any of the the second elements (i.e., 4 and 8) is ever > 4 and false otherwise. 8 > 4, so the result is true.
From the official docs, the any? method:
Passes each element of the collection to the given block. The method
returns true if the block ever returns a value other than false or
nil. If the block is not given, Ruby adds an implicit block of { |obj|
obj } that will cause any? to return true if at least one of the
collection members is not false or nil.
What Hash#any? does is yield arrays of two elements to a given block and return true if the evaluation of the block returned something truthy (not false or nil) and false otherwise.
As for why you get two values if you pass a block with two arguments - this is called unpacking.
def foo
yield [42, 6 * 9]
end
# only one argument, array is not unpacked
foo { |numbers| p numbers } # prints [42, 54]
# two arguments, the array is being unpacked
foo { |x, y| p x, y } # prints 42 \n 54

Destructive map method with control flow returns unexpected nils

When I run this, it correctly changes the 3 in array to "blue", but it changes all other elements to nil.
array = [1, 2, 3, 4]
array.map! do |number|
if number == 3
array[number] = "blue"
end
end
Since I introduced the if statement, I expect it to leave everything else alone. Can someone explain why that's happening and how to get it to only modify the element isolated with the if statement?
When you run map! it:
Invokes the given block once for each element of self, replacing the
element with the value returned by the block.
So when the number doesn't match 3 the block is returning nil - when it is 3 you actually don't need the assignment you're using, having simply "blue" would have the same effect.
This should accomplish what you're trying to do:
array = [1, 2, 3, 4]
array.map! do |number|
number == 3 ? "blue" : number
end
See http://ruby-doc.org/core-2.2.0/Array.html#method-i-map-21

Resources