удалить элементы из списка структуры класса case при обнаружении дубликата scala с помощью foldleft

#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, что было удалено?