如果在scala 中发现重复,则删除case类的两个对象
示例列表如下:
val pets = List(
Pet("cat", "sassy", 2), Pet("cat", "bella", 3),
Pet("dog", "poppy", 3), Pet("dog", "bodie", 4), Pet("dog", "poppy", 2),
Pet("bird", "coco", 2), Pet("bird", "kiwi", 1),
Pet("hen", "kiwi", 2), Pet("horse", "kiwi", 1),
Pet("cow", "mow", 2)
)
我想检查列表中是否有重复项,并将它们从列表中删除。在这种情况下,我的列表将只有一个值,在本例中,它将是值Pet("cow", "mow", 2)
,其他值将消失。这里不考虑Pet("hen", "kiwi", 2)
、Pet("horse", "kiwi", 1)
;猕猴桃";重复。
case class Pet(species: String, name: String, age: Int)
val pets = List(
Pet("cat", "sassy", 2), Pet("cat", "bella", 3),
Pet("dog", "poppy", 3), Pet("dog", "bodie", 4), Pet("dog", "poppy", 2),
Pet("bird", "coco", 2), Pet("bird", "kiwi", 1),
Pet("hen", "kiwi", 2), Pet("horse", "kiwi", 1),
Pet("cow", "mow", 2)
)
def customEqualsPet(x : Pet, y: Pet) = (x.species == y.species || x.name== y.name)
val petsOut = pets.foldLeft(Nil : List[Pet]) {(list, item) =>
val exists = list.find(x => customEqualsPet(item, x))
if (exists.isEmpty) {
item :: list
} else {
println("once......"+list)
println("once......"+item)
list.filter(u=>{(u.name!=item.name) || (u.species!=item.species)})
}
}.reverse
println(cc)
似乎干扰了输出。感谢您的帮助预期输出
List( Pet("cow", "mow", 2))
您的另一个选择是,首先查找要删除的所有名称和物种:
val speciesToRemove = pets.groupBy(_.species).filter(_._2.length > 1).keySet
val namesToRemove = pets.groupBy(_.name).filter(_._2.length > 1).keySet
然后通过它们进行过滤:
pets.filterNot(pet => speciesToRemove.contains(pet.species) || namesToRemove.contains(pet.name))
代码在Scastie中运行。
效率不高,但简洁易懂。(不需要foldLeft()
。(
val species = pets.groupBy(_.species)
val names = pets.groupBy(_.name)
pets.filter(p => species(p.species).length +
names(p.name).length == 2)
//res0: List[Pet] = List(Pet(cow,mow,2))
如果species
指定不能出现在name
字符串中,而name
字符串不能作为species
出现,则可以将其浓缩。
val groups = pets.groupBy(_.species) ++ pets.groupBy(_.name)
pets.filter(p => groups(p.species).length +
groups(p.name).length == 2)
如果您想要唯一元素和所有非唯一元素的列表。。。
val (unique, dups) =
pets.partition(p => groups(p.species).length +
groups(p.name).length == 2)