Home > Software engineering >  Scala: How to find matching items in a List
Scala: How to find matching items in a List

Time:06-02

There is a guest coming for lunch and at each table there is one person (bob, peter, simon or sarah) and on that table there is one fruit bowl.

I need to score the matches of fruit in order to decide which person/table the guest should with/at.

My thinking is that I need to give each person a score based on the amount of matches they have with the guests fruit. So I need to compare a List[Fruit] with a List[Fruit] then return the Person

I need to return a Map as per below

  case class Person(str: String, value: List[Fruit])

  case class Fruit(fruit: String)

  val guest: Person = Person("Unknown", List(Fruit("Apple"), Fruit("Pear"), Fruit("Grapes")))
  
  val bob: Person = Person("Bob", List(Fruit("Apple"), Fruit("Pear"), Fruit("Grapes"))) // 3
  val peter: Person = Person("Peter", List(Fruit("Apple"), Fruit("Pineapple"), Fruit("Mango"))) // 1
  val simon: Person = Person("Simon", List(Fruit("Apple"), Fruit("Pear"), Fruit("Mango"))) // 2
  val sarah: Person = Person("sarah", List(Fruit("Pear"), Fruit("Grapes"), Fruit("Mango"))) // 2

  Map( 3 ->
    Person("Bob", List(Fruit("Apple"), Fruit("Pear"), Fruit("Grapes"))),
    2 -> Person("Simon", List(Fruit("Apple"), Fruit("Pear"), Fruit("Mango"))),
    2 -> Person("sarah", List(Fruit("Pear"), Fruit("Grapes"), Fruit("Mango"))),
    1 -> Person("Peter", List(Fruit("Apple"), Fruit("Pineapple"), Fruit("Mango")))
  )

CodePudding user response:

Although the other answer should work, but it is kind of like imperative approach, and personally I wouldn't use mutation as far as possible, I would recommend using the intersection of fruits set in order to find the fruits in common:

val persons = List(bob, peter, simon, sarah)

persons.map { person => 
  val fruitsInCommon = (person.value.toSet & guest.value.toSet).size
  fruitsInCommon -> person
}.sortBy(_._1).toMap

You can also use .view on the persons if you'd like to.

CodePudding user response:

This will give a map that groups people by number of fruit they have in common with the guest:

val persons = List(bob, peter, simon, sarah)

persons.groupMap(_.value.intersect(guest.value).size)(_.str)

// Map(1 -> List(Peter), 2 -> List(Simon, sarah), 3 -> List(Bob))

Using Set would be more efficient, perhaps as a calculated value on Person:

case class Person(str: String, value: List[Fruit]) {
  lazy val fruitSet = value.toSet
}

persons.groupMap(_.fruitSet.intersect(guest.fruitSet).size)(_.str)
  • Related