Boolean operators for DataSeries#99
Conversation
`<`,`>`,`<=`,`>=` have been added for comparision of values of two DataSeries. Keys are not considered while comparing.
|
Because For example, all arithmetic tests are called Could you rename your tests from This convention is not perfect and we can change it later, but for now, let's follow it. PS. For example, I don't know how many tests you have added. Four? Or am I missing some? |
|
You should have one assertion per test. If you have multiple assertions, consider having multiple tests. Imagine that this test is red: testGreaterThan
| firstSeries secondSeries |
firstSeries := DataSeries withKeys: #(a b c) values: #(1 0.4 'a').
secondSeries := DataSeries withKeys: #(1 2 3) values: #(1 0.1 'b').
self assert: firstSeries > secondSeries equals: #(false true false).
firstSeries := DataSeries withKeys: #(a b c) values: #(0.8 0.4 1).
secondSeries := DataSeries withKeys: #(a b c) values: #(true false true).
self assert: firstSeries >= 0.8 equals: secondSeries.Then we don't know if it's because comparison of series-to-series fails or is it series-to-scalar. It is definitely better to split that test into two separate tests. |
< aDataSeriesOrNumber
"Element-wise comparision between two DataSeries.
Does not consider keys for comparision.
Returns an Array."Why does it return an array? Same logic applies to all boolean operators |
(aDataSeriesOrNumber isNumber)
ifTrue: [ ... ]
ifFalse: [ ... ]We should try to avoid type checking with if statements. Also, you don't need parenthesis around |
The problem I had with returning Series is what should the keys/index be? Keys of first series, or second series, or 1, 2, 3... firstSeries := DataSeries withKeys: #(a b c) values: #(1 0.4 'a').
secondSeries := DataSeries withKeys: #(1 2 3) values: #(1 0.1 'b').What should keys of |
I think that the logic there should be the same as for arithmetic operations. testArithmeticsAddSeriesToSeriesDifferentKeys
| firstSeries secondSeries |
firstSeries := DataSeries withKeys: #(x y z) values: #(1 2 3) name: #X.
secondSeries := DataSeries withKeys: #(a b c) values: #(3 4 5) name: #X.
self should: [ firstSeries + secondSeries ] raise: Error.Maybe it is too restrictive (we can discuss that). But I was thinking of the use cases first. |
|
You need to write tests for all possible scenarios of comparisons:
Same as for all arithmetic operations. |
|
You have added 4 methods with same source code and only 2 symbols that change: < aDataSeriesOrNumber
"Element-wise comparision between two DataSeries.
Does not consider keys for comparision.
Returns an Array."
(aDataSeriesOrNumber isNumber)
ifTrue: [ ^ aDataSeriesOrNumber adaptToCollection: self andSend: #< ]
ifFalse: [
^ (1 to: self size) collect: [ :i |
(self values at: i) < (aDataSeriesOrNumber values at: i)
]].
<= aDataSeriesOrNumber
"Element-wise comparision between two DataSeries.
Does not consider keys for comparision.
Returns an Array."
(aDataSeriesOrNumber isNumber)
ifTrue: [ ^ aDataSeriesOrNumber adaptToCollection: self andSend: #<= ]
ifFalse: [
^ (1 to: self size) collect: [ :i |
(self values at: i) <= (aDataSeriesOrNumber values at: i)
]].> aDataSeriesOrNumber
"Element-wise comparision between two DataSeries.
Does not consider keys for comparision.
Returns an Array."
(aDataSeriesOrNumber isNumber)
ifTrue: [ ^ aDataSeriesOrNumber adaptToCollection: self andSend: #> ]
ifFalse: [
^ (1 to: self size) collect: [ :i |
(self values at: i) > (aDataSeriesOrNumber values at: i)
]].>= aDataSeriesOrNumber
"Element-wise comparision between two DataSeries.
Does not consider keys for comparision.
Returns an Array."
(aDataSeriesOrNumber isNumber)
ifTrue: [ ^ aDataSeriesOrNumber adaptToCollection: self andSend: #>= ]
ifFalse: [
^ (1 to: self size) collect: [ :i |
(self values at: i) >= (aDataSeriesOrNumber values at: i)
]].That's a lot of duplicated code and we should avoid it (imagine that someone changes implementation of one of these methods, will he remember to make equivalent change to other 3?) |
|
I suggest the following implementation: DataSeries >> < arg
^ arg adaptToCollection: self andSend: #<.DataSeries >> > arg
^ arg adaptToCollection: self andSend: #>.DataSeries >> <= arg
^ arg adaptToCollection: self andSend: #<=.DataSeries >> >= arg
^ arg adaptToCollection: self andSend: #>=.It fixes all the problems mentioned above |
Refactored and added more tests
|
Yes, it fixes the problems! :) I did try it early and it did not work, I must have been using it in a wrong example. I have made changes as suggested. array with series does not work, since array does not understand boolean operators > < >= <=. |
Issue: #96
Tasks: