代码之家  ›  专栏  ›  技术社区  ›  Sunil Rajashekar

基于条件的Zip非序列列表

  •  1
  • Sunil Rajashekar  · 技术社区  · 7 年前

    它们可能不按顺序排列。最好的方法是什么?

    object Main extends App {
       case class SalesDoc(val id: Int, val name: String, val requestId: String) {}
       val list = List(
         SalesDoc(1, "ILLEGAL", "1"),
         SalesDoc(2, "DirectRetailCM", "1"),
    
         SalesDoc(3, "DirectRetailOffsetInvoice", "2"),
         SalesDoc(4, "DirectRetailCM", "2"),
         SalesDoc(5, "OTHER", "2"),
    
         SalesDoc(5, "DirectRetailCM", "LEFTOUT"),
         SalesDoc(6, "ILLEGAL2", "4"),
    
         SalesDoc(5, "OTHER", "3"),
         SalesDoc(7, "DirectRetailOffsetInvoice", "4"),
         SalesDoc(8, "DirectRetailCM", "4")
      )
    
     // I expect zip results of drOffsetInvoice and drCms as
    List(
      (SalesDoc(3, "DirectRetailOffsetInvoice", "2"), SalesDoc(4, "DirectRetailCM", "2")),
      (SalesDoc(7, "DirectRetailOffsetInvoice", "4"), SalesDoc(8, "DirectRetailCM", "4"))
      )
    }
    

    我能想到的最初方法是

    • 组DirectRetailOffset语音列表。过滤器(e=>e.name==“DirectRetailOffsetInvoice”)
    • 同时压缩-但可能不在序列中
    • 可能有没有对应的行

    3 回复  |  直到 7 年前
        1
  •  3
  •   Tyler    7 年前
    // You don't need the val keyword for a case class
    case class SalesDoc(id: Int, name: String, requestId: String)
    
    val list = List(
      SalesDoc(1, "ILLEGAL", "1"),
      SalesDoc(2, "DirectRetailCM", "1"),
    
      SalesDoc(3, "DirectRetailOffsetInvoice", "2"),
      SalesDoc(4, "DirectRetailCM", "2"),
      SalesDoc(5, "OTHER", "2"),
    
      SalesDoc(5, "DirectRetailCM", "LEFTOUT"),
      SalesDoc(6, "ILLEGAL2", "4"),
    
      SalesDoc(5, "OTHER", "3"),
      SalesDoc(7, "DirectRetailOffsetInvoice", "4"),
      SalesDoc(8, "DirectRetailCM", "4")
    )
    
    // Find all of the DirectRetailOffsetInvoice items
    val offsets = list.filter(_.name == "DirectRetailOffsetInvoice")
    
    // Map over all of the DirectRetailOffsetInvoice items and see if there is matching DirectRetailCM item
    val maybeMatched = offsets.map(offset => {
      val maybeCm = list.find(i => i.requestId == offset.requestId && i.name == "DirectRetailCM")
    
      // Return a tuple of type (SalesDoc, Option[SalesDoc])
      (offset, maybeCm)
    })
    
    // Map over the tuples and only take the ones where there was a match, and extract it from the Option to create a tuple of (SalesDoc, SalesDoc)
    val output = maybeMatched.collect { case (s1, Some(s2)) => (s1, s2) }
    
    output.foreach(println)
    // (SalesDoc(3,DirectRetailOffsetInvoice,2),SalesDoc(4,DirectRetailCM,2))
    // (SalesDoc(7,DirectRetailOffsetInvoice,4),SalesDoc(8,DirectRetailCM,4))
    
        2
  •  1
  •   n1r3    7 年前

    使用标准Scala组合器可以实现这一点

    list
      .filter(sd => sd.name == "DirectRetailCM" || sd.name == "DirectRetailOffsetInvoice")
      .groupBy(_.requestId)
      .flatMap {
         case (_, List(a,b)) => List(a->b)
         case _ => List.empty
      }
    

    这给了你:

     res3: scala.collection.immutable.Map[SalesDoc,SalesDoc] = 
           Map(
             SalesDoc(3,DirectRetailOffsetInvoice,2) -> SalesDoc(4,DirectRetailCM,2), 
             SalesDoc(7,DirectRetailOffsetInvoice,4) -> SalesDoc(8,DirectRetailCM,4))
    

    如果输入序列未按排序 DirectRetailOffsetInvoice DirectRetailCM ,您需要处理它。

        3
  •  1
  •   Jeffrey Chung    7 年前
    list.filter(s => s.name == "DirectRetailCM" || s.name == "DirectRetailOffsetInvoice")
        .groupBy(_.requestId)
        .collect { case (_, List(a, b)) => (a, b) }
        .toList
    
    // List[(SalesDoc, SalesDoc)]