Reputation: 1781
Sample code:
val todayCount = keyValue.value.filter {
val after = it.expectedArrivalDate?.after(today)
val before = it.expectedArrivalDate?.before(tomorrow)
after != null && before != null && after && before
}.size
If it.expectedArrivalDate
were not nullable
I would write something like that:
val todayCount = keyValue.value.filter {
it.expectedArrivalDate.after(today) && it.expectedArrivalDate.before(tomorrow)
}.size
Is it possible to simplify my code?
Upvotes: 1
Views: 5050
Reputation: 672
An alternative without an extension function: as all comparisons are based on the same field, you can actually map it while removing all nulls.
Here's a sample code with a dummy travel class so that you can see it compiles:
data class Travel(var expectedArrivalDate: Date? = null);
lateinit var keyValue: Map.Entry<String, List<Travel>>;
val today = Date.from(Instant.now())
val tomorrow = Date.from(Instant.now().plusSeconds(86400))
val todayCount = keyValue.value.mapNotNull(Travel::expectedArrivalDate).count {
it.after(today) && it.before(tomorrow)
}
Gets the solution down to 125 characters and gets close to the code you had in mind.
Upvotes: 0
Reputation: 6988
You can create an extension functions to simplify that check.
Assuming that the type of expectedArrivalDate
is Date
, you could add after
and before
functions for the nullable Date type Date?
that would return false if the instance is null, or call the original after
/before
functions if not null:
fun Date?.after(anotherDate: Date): Boolean = this?.after(anotherDate) ?: false
fun Date?.before(anotherDate: Date): Boolean = this?.before(anotherDate) ?: false
and leave your code as it is:
val todayCount = keyValue.value.filter {
it.expectedArrivalDate.after(today) && it.expectedArrivalDate.before(tomorrow)
}.size
or you could just use the implementation directly in your code:
val todayCount = keyValue.value.filter {
(it.expectedArrivalDate?.after(today) ?: false) && (it.expectedArrivalDate?.before(tomorrow) ?: false)
}.size
Upvotes: 2
Reputation: 408
Not sure if this can be considered a simplification but as another option you can:
val todayCount = keyValue.value.filter {
it.expectedArrivalDate?.takeIf{d -> d.after(today)}?.takeIf{d -> d.before(tomorrow)}?.let{true}?:false
}.size
Upvotes: 0
Reputation: 18627
An alternative to extension functions or Elvis operators is simply == true
.
In Java, where ==
compares references, that would be dangerous, as it would fail for any new Boolean instances. But in Kotlin, ==
compares values using .equals()
(after making the necessary null checks), so would handle that case perfectly well.
So your code could be:
val todayCount = keyValue.value.filter {
it.expectedArrivalDate?.after(today) == true
&& it.expectedArrivalDate?.before(tomorrow) == true
}.size
Similarly, if you wanted null
to count as true
, you could use != false
.
It's arguably not the most elegant solution, but it's probably the simplest!
Upvotes: 4
Reputation: 58892
Consider using variable re-declaration using ?:
variable re-declaration (and shadowing).
fun leftPad(value: String, length: Int? = null, char: Char? = null): String { val length = length ?: 4 val char = char ?: ' '
Upvotes: 0