如何使用scala case类作为函数参数来指定要使用的不同字段?

如何使用scala case类作为函数参数来指定要使用的不同字段?,scala,case-class,Scala,Case Class,我有一些重复的代码,因为必须在一个案例类中的3个不同字段上进行分组,然后用这些字段填充一个新的案例类。因为它们共享一个公共模式,所以我应该可以执行一个函数,该函数可以接受3个不同字段的输入,并相应地进行填充。然而,我并不完全确定如何做到这一点 模式: case class Transaction( senderBank: Bank, receiverBank: Bank, intermediaryBank: Bank) case class Bank( name: String

我有一些重复的代码,因为必须在一个案例类中的3个不同字段上进行分组,然后用这些字段填充一个新的案例类。因为它们共享一个公共模式,所以我应该可以执行一个函数,该函数可以接受3个不同字段的输入,并相应地进行填充。然而,我并不完全确定如何做到这一点

模式:

case class Transaction(
  senderBank: Bank,
  receiverBank: Bank,
  intermediaryBank: Bank)

case class Bank(
  name: String,
  country: Option[String],
  countryCode: Option[String])

case class GroupedBank(
  name: String,
  country: Option[String],
  countryCode: Option[String],
  bankType: String)
我尝试执行的当前函数:

def groupedBank(transactionSeq: Seq[Transaction], bankName: Bank, bankTypeString: String): Iterable[Seq[GroupedBank]] = {
 transactionSeq.groupBy(_ => bankName.name).map {
  case (key, transactionSeq) =>
    val bankGroupedSeq = transactionSeq.map(_ => {
      GroupedBank(
        name = bankName.name,
        country = bankName.country,
        countryCode = bankName.countryCode,
        bankType = bankTypeString)
    })
    bankGroupedSeq
  }
}

我需要对
SenderBank
receiverBank
intermediaryBank
进行分组。但是,我不确定如何在函数参数
bankName
中正确引用它们。因此,对于
SenderBank
,我希望执行类似于
Transaction.SenderBank
的操作,这将指向
SenderBank
的名称、国家等正确字段。对于
receiverBank
,它应该是类似的,因此
交易。receiverBank
,然后它引用了
receiverBank
的正确字段,依此类推。对于
intermediaryBank
同样的逻辑。因此,我的问题是,我如何才能完成这样的事情,或者是否有其他更合适的方式

您可以传递一个函数,从交易中提取具有正确类型的银行:

def groupedBank(
  transactionSeq: Seq[Transaction], 
  getBank: Transaction => Bank, 
  bankTypeString: String
): Iterable[Seq[GroupedBank]] = {
  transactionSeq.groupBy(getBank(_).name).map {
    case (key, transactionSeq) =>
      transactionSeq.map { transaction =>
        val bank = getBank(transaction)
        GroupedBank(
          name = bank.name,
          country = bank.country,
          countryCode = bank.countryCode,
          bankType = bankTypeString)
      }
  }
}
然后这样称呼它:

groupedBank(transactionSeq, _.senderBank, "sender")

将银行类型概念抽象为一个单独的特征也是一个好主意:

sealed trait BankGroup {
  def name: String
  def getBank(transaction: Transaction): Bank

  def groupBanks(transactionSeq: Seq[Transaction]): Iterable[Seq[GroupedBank]] = {
    transactionSeq.groupBy(getBank(_).name).map {
      case (key, transactionSeq) =>
        transactionSeq.map { transaction =>
          val bank = getBank(transaction)
          GroupedBank(
            name = bank.name,
            country = bank.country,
            countryCode = bank.countryCode,
            bankType = name)
        }
    }
  }
}

object BankGroup {
  object Sender extends BankGroup {
    def name: String = "sender"
    def getBank(transaction: Transaction): Bank = transaction.senderBank
  }

  object Receiver extends BankGroup {
    def name: String = "receiver"
    def getBank(transaction: Transaction): Bank = transaction.receiverBank
  }

  object Intermediary extends BankGroup {
    def name: String = "intermediary"
    def getBank(transaction: Transaction): Bank = transaction.intermediaryBank
  }

  val values: Seq[BankGroup] = Seq(Sender, Receiver, Intermediary)
  def byName(name: String): BankGroup = values.find(_.name == name)
    .getOrElse(sys.error(s"unknown bank type: $name"))
}
你可以用以下方式之一来称呼它:

BankGroup.Sender.groupBanks(transactionSeq)
BankGroup.byName("sender").groupBanks(transactionSeq)

对不起,不清楚你在做什么。您是否想要
transactionSeq.groupBy(\uu.senderBank.name)
transactionSeq.groupBy(\uu.receiverBank.name)
transactionSeq.groupBy(\uu.intermediaryBank.name)
?@DmytroMitin,是的。很抱歉,我有点不清楚。@DmytroMitin,但这在函数中是什么样子的?