我正在尝试仅收集唯一的对象,然后将它们输出到CSV文件 下面的代码可以吗?还是有正确的方法?
interface f {
val s1: String
val s2: String
fun tot():Int
}
data class A(override val s1: String, override val s2:String, val sub_cost1: Int, val sub_cost2: Int) : f {
override fun tot() : Int { return sub_cost1 + sub_cost2}
}
data class B(override val s1: String, override val s2:String, val b_cost: Int, val area: Int) : f {
override fun tot() : Int { return b_cost}
}
data class C(override val s1: String, override val s2:String, val c_cost: Int) : f{
override fun tot() : Int { return c_cost}
}
fun main(args: Array<String>) {
val s = mutableSetOf<f>()
s.add(C("a0","b0", 1))
s.add(C("a0","b0", 1)) // equal to first elem, must not be added!
s.add(A("a1","a2", 2, 3))
s.add(B("b1","b2", 5, 6))
// to output into CSV file
println("s1, s2, sub_cost1, sub_cost2, b.cost, c.cost, tot")
for (i in s) {
when (i) {
is A -> println("${i.s1}, ${i.s2}, ${i.sub_cost1}, ${ i.sub_cost2}, , , ${i.tot()}")
is B -> println("${i.s1}, ${i.s2}, , , ${i.b_cost}, , ${i.tot()}")
is C -> println("${i.s1}, ${i.s2}, , , , ${i.c_cost}, ${i.tot()}")
}
}
}
预期输出:
s1,s2,sub_cost1,sub_cost2,b_cost,c_cost,tot
a0,b0,,,,,1,1
a1,a2,2,3,,,5
b1,b2,,,,5,5
答案 0 :(得分:1)
是的,使用Set
自动防止重复很普遍。我认为它当然算是“正确的”,在这里没有什么更好的建议。
请注意,这仅在集合可以告诉为重复项时才有效;因此,对象需要具有equals()
方法的适当实现,或者您需要给集合提供一个Comparator
。在这种情况下,您使用的是data class
,它会自动为您提供合适的equals()
实现。
使用Set
也可以使任何人都清楚自己的意图。
(另一个优点是大多数实现都可以非常快速地检查对象的存在与否。它们也有缺点:与简单的List
相比,它们倾向于占用更多的内存。 ,但是较简单的实现没有一致或可预测的迭代顺序。但这通常不是问题-如果需要有序的迭代,则可以使用LinkedHashSet
。)
我可能要看的是更改代码中的一件事是when
;这要求代码的主要部分了解f
的每个实现及其内部。最佳方法并不明显。如果您认为其中的字符串处理与对象内部的关系比所创建的CSV格式的关系更紧密,则可以在接口中添加一个返回String
的方法(标准{{1} }方法或诸如toString()
之类的方法;那么每个类都可以按照自己的意愿实现它,而主代码可以调用它,而不必关心细节。 (或者,如果将CSV详细信息更好地放在一起,那么toCSVLine()
可能会更好。或者您可能会发现一种混合方法,其中when
界面中的方法可以提供所需的一切无需了解实施情况。)
(此外,我会大写f
接口。Kotlin(和Java)编码标准都以大写字母开头的接口名称,就像类名一样。)