#scala
#скала
Вопрос:
Удалите оба объекта класса case, если найдены дубликаты в scala
Примерный список выглядит следующим образом:
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))
Комментарии:
1. здесь название вида другое, и оно рассматривается как уникальное.
2. вид не может повторяться или название не может повторяться, Возраст может повторяться
3. где вы используете spark в этом ?
4. нет , я не использую spark . только ядро scala
5. Ожидаемый результат выше: Список (домашнее животное («корова», «косить», 2)) . Примечание: имя или вид не могут быть повторены в классе регистра элемента списка. Это означает, что то же имя или тот же тип вида не допускаются в качестве элемента для построения другого списка
Ответ №1:
Другой вариант, который у вас есть, — сначала найти все имена и виды, которые вы хотите удалить:
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.
Комментарии:
1. для вашего вышеупомянутого решения я хочу удалить виды, если найден дубликат или комбинация {имя и возраст} найденный дубликат может быть удален. Ожидаемый результат будет следующим: Список (Домашнее животное (корова, косить, 2), Домашнее животное («курица», «киви», 2), Домашнее животное («лошадь», «киви», 1))
2. @santanumohanty, я не понимаю вашего комментария, вы сказали, что ожидаемый результат
List(Pet("cow", "mow", 2))
— это то, что обеспечивается моим ответом.3. Ваш приведенный выше ответ является правильным и лучшим решением для получения списка (домашнее животное («корова», «косить», 2)). Я просто спрашиваю, хочу ли я улучшить, чтобы удалить виды, если найден дубликат, или комбинацию {имя и возраст}, найденный дубликат, чтобы удалить. Тогда приведенный выше пример Ожидаемого результата будет следующим: Список (Домашнее животное (корова, косить, 2), Домашнее животное («курица», «киви», 2), Домашнее животное («лошадь», «киви», 1)). Могу ли я сделать это в приведенном выше коде для изменения, передав несколько полей в group by
4. если я захочу удалить дубликат по комбинации {name и age}, какие изменения вы думаете
5. у меня не работает, если я добавлю age val namesToRemove = pets.groupBy(rec => (rec.name , рек.возраст)). фильтр (_._2.length > 1).Набор ключей
Ответ №2:
Не очень эффективно, но лаконично и легко для понимания. ( 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
строка не может отображаться как a 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)
Комментарии:
1. могу ли я добавить println, что было удалено?