转换列表,过滤掉导致异常的项目
Transform a list, filtering out the items that cause an exception
如何转换这个字符串数组:
"2018-05-08T23:22:49Z"
"n/a"
"2018-05-07T16:37:00Z"
到使用高阶函数的日期数组,例如 map
、flatMap
或 reduce
?
我知道使用 forEach
可以做到这一点,但我有兴趣涉及 Kotlin 高阶函数:
val stringArray
= mutableListOf("2018-05-08T23:22:49Z", "n/a", "2018-05-07T16:37:00Z")
val dateArray = mutableListOf<Date>()
stringArray.forEach {
try {
val date = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US)
.parse(it)
dateArray.add(date)
} catch (e: ParseException) {
//* Just prevents app from crash */
}
}
您正在寻找一种可以为每个输入元素输出零个或一个元素的转换。这是flatMap
。平面映射函数的结果必须是 Iterable
,所以:
val dateArray = stringArray.flatMap {
try {
listOf(SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US).parse(it))
} catch (e: ParseException) {
emptyList<Date>()
}
}
根据@pwolaq
的输入添加以下内容:
强烈建议提取 SimpleDateFormat
实例,因为它具有重量级初始化。此外,mapNotNull
的解决方案比 flatMap
更干净,我没有意识到这一点。如果您添加一个我认为 Kotlin 标准库中缺少的函数,这将变得特别方便:
inline fun <T> runOrNull(block: () -> T) = try {
block()
} catch (t: Throwable) {
null
}
在你的工具箱中有了这个,你可以说:
val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US)
val dateArray: List<Date> = stringArray.mapNotNull {
runOrNull { formatter.parse(it) }
}
使用 mapNotNull
val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US)
val dates = listOf("2018-05-08T23:22:49Z", "n/a", "2018-05-07T16:37:00Z")
.mapNotNull {
try {
format.parse(it)
} catch (e: ParseException) {
null
}
}
println(dates)
这避免了为列表中的每个项目创建一个列表,它将错误日期映射到空值,并且 mapNotNull 从列表中删除空值。
使用扩展函数
您还可以将 tryOrRemove 提取到扩展函数中,使代码如下所示:
val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US)
fun <T, U: Any> Iterable<T>.tryOrRemove(block:(T)->U): List<U> {
return mapNotNull {
try {
block(it)
} catch (ex: Throwable) {
null
}
}
}
val dates = listOf("2018-05-08T23:22:49Z", "n/a", "2018-05-07T16:37:00Z")
.tryOrRemove(format::parse)
println(dates)
使用过滤器
我已经根据唯一的错误日期 n/a 编写了它,这简化了它。
val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US)
val dates = listOf("2018-05-08T23:22:49Z", "n/a", "2018-05-07T16:37:00Z")
.filter { it != "n/a" }
.map(format::parse)
println(dates)
如何转换这个字符串数组:
"2018-05-08T23:22:49Z"
"n/a"
"2018-05-07T16:37:00Z"
到使用高阶函数的日期数组,例如 map
、flatMap
或 reduce
?
我知道使用 forEach
可以做到这一点,但我有兴趣涉及 Kotlin 高阶函数:
val stringArray
= mutableListOf("2018-05-08T23:22:49Z", "n/a", "2018-05-07T16:37:00Z")
val dateArray = mutableListOf<Date>()
stringArray.forEach {
try {
val date = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US)
.parse(it)
dateArray.add(date)
} catch (e: ParseException) {
//* Just prevents app from crash */
}
}
您正在寻找一种可以为每个输入元素输出零个或一个元素的转换。这是flatMap
。平面映射函数的结果必须是 Iterable
,所以:
val dateArray = stringArray.flatMap {
try {
listOf(SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US).parse(it))
} catch (e: ParseException) {
emptyList<Date>()
}
}
根据@pwolaq
的输入添加以下内容:
强烈建议提取 SimpleDateFormat
实例,因为它具有重量级初始化。此外,mapNotNull
的解决方案比 flatMap
更干净,我没有意识到这一点。如果您添加一个我认为 Kotlin 标准库中缺少的函数,这将变得特别方便:
inline fun <T> runOrNull(block: () -> T) = try {
block()
} catch (t: Throwable) {
null
}
在你的工具箱中有了这个,你可以说:
val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US)
val dateArray: List<Date> = stringArray.mapNotNull {
runOrNull { formatter.parse(it) }
}
使用 mapNotNull
val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US)
val dates = listOf("2018-05-08T23:22:49Z", "n/a", "2018-05-07T16:37:00Z")
.mapNotNull {
try {
format.parse(it)
} catch (e: ParseException) {
null
}
}
println(dates)
这避免了为列表中的每个项目创建一个列表,它将错误日期映射到空值,并且 mapNotNull 从列表中删除空值。
使用扩展函数
您还可以将 tryOrRemove 提取到扩展函数中,使代码如下所示:
val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US)
fun <T, U: Any> Iterable<T>.tryOrRemove(block:(T)->U): List<U> {
return mapNotNull {
try {
block(it)
} catch (ex: Throwable) {
null
}
}
}
val dates = listOf("2018-05-08T23:22:49Z", "n/a", "2018-05-07T16:37:00Z")
.tryOrRemove(format::parse)
println(dates)
使用过滤器
我已经根据唯一的错误日期 n/a 编写了它,这简化了它。
val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US)
val dates = listOf("2018-05-08T23:22:49Z", "n/a", "2018-05-07T16:37:00Z")
.filter { it != "n/a" }
.map(format::parse)
println(dates)