问题描述
我有一个包含数据的源列表,我想将其分类为3个包含清除数据,更新数据并记录的列表。来自源的所有元素都必须在日志列表中。所有具有非空值的元素都必须在清除列表中,并且如果更新了标志,则该元素也必须出现在更新的文件夹中。
根据示例:
- updated = 2,4 el
- 已记录= 1,2,3,4 el
- cleaned = 3,4 el
您能帮我简化书面代码吗?
When I choose a movie by "<movie_name>" and play
Examples: {'datafile' : 'src/main/resources/data/testData.xls','sheetName' : 'movie_demo'}
解决方法
我个人认为这是使用递归可以最好地解决的问题。
该代码较大,但恕我直言,更易于理解和更改。
type Result = (List[Logged],List[Cleaned],List[Updated])
def process(data: List[Source]): Result = {
@annotation.tailrec
def loop(remaining: List[Source],logged: List[Logged],cleaned: List[Cleaned],updated: List[Updated]): Result =
remaining match {
case Source(Some(value),date,true) :: xs =>
loop(
remaining = xs,Logged(value = value,date) :: logged,Cleaned(value,date) :: cleaned,Updated(value,date) :: updated
)
case Source(Some(value),false) :: xs =>
loop(
remaining = xs,updated
)
case Source(None,_) :: xs =>
loop(
remaining = xs,Logged(value = "",cleaned,updated
)
case Nil=>
// If the order is not important,remove all the reverse.
(
logged.reverse,cleaned.reverse,updated.reverse
)
}
loop(remaining = data,logged = List.empty,cleaned = List.empty,updated = List.empty)
}
您可以看到运行here的代码。
,您可以构造自己的折叠运算符,并使用foldRight方法传递该折叠运算符:
type Targets = (List[Updated],List[Logged],List[Cleaned])
val target = sources.foldRight(List.empty[Updated],List.empty[Logged],List.empty[Cleaned])(process)
def process(el: Source,acc: Targets): Targets = acc match {
case (updated,logged,cleaned) => el match {
case Source(None,false) =>
(updated,Logged("",cleaned)
case Source(Some(value),Logged(value,date) :: cleaned)
case Source(None,true) =>
(Updated("",date) :: updated,true) =>
(Updated(value,date) :: cleaned)
}
}
,
除非存在严重的性能问题,否则只需处理列表三遍:
val target =
(
sources.flatMap { el =>
if (el.isUpdate) Some(Updated(el.value.getOrElse(""),el.date)) else None
},sources.map(el => Logged(el.value.getOrElse(""),el.date)),sources.flatMap { el =>
el.value.map(d => Cleaned(d,el.date))
}
)