2013-07-24 20 views
12

Moodb ile bir play2.1 uygulaması yazıyorum ve model objem biraz geniş. DB'deki bir girişi güncelleştirirken, formdaki temp nesnesini DB'de bulunanlarla karşılaştırmalıyım, böylece güncelleştirme sorgusunu oluşturabilir (ve değişiklikleri kaydedebilirim).vaka sınıfı veri üyeleri üzerinde yineleyin

Genelde 2 örnek almanın ve bunlardan fark almanın bir yolunu arıyorum. Her bir veri üyesi üzerinde yineleme, uzun, sabit kodlanmış ve hata eğilimli (eğer a.firstName.equalsIgnoreCase (b.firstName)), böylece tüm veri üyeleri üzerinde yineleme ve onları yatay olarak karşılaştırmak için bir yol arıyorum (bir isim haritası - > değer, her seferinde veri üyelerini aynı sırayla numaralandırmak için güvenebileceğim bir liste yapar.

herhangi bir fikir?

case class Customer(
    id: Option[BSONObjectID] = Some(BSONObjectID.generate), 
    firstName: String, 
    middleName: String, 
    lastName: String, 
    address: List[Address], 
    phoneNumbers: List[PhoneNumber], 
    email: String, 
    creationTime: Option[DateTime] = Some(DateTime.now()), 
    lastUpdateTime: Option[DateTime] = Some(DateTime.now()) 
) 

her üç çözümler aşağıda büyük, ama hala sağ, alanın adını alamıyor? o ı değişikliği giriş yapabilirsiniz anlamına gelir, ancak değil etkilenen hangi alanda ...

+0

Bazı kod parçacıkları gönderebilir misiniz? Vaka sınıflarınız, bazı örnek örnekler ve elde etmek istediğiniz sonuç nedir? –

cevap

8

Malte_Schwerhoff cevabı @ üzerinde genişletilmesi, potansiyel farklılıkları endeksler oluşturulmuş sadece bir özyinelemeli fark yöntemi oluşturmak, ama bu dizinde yeni değere onları eşleştirilmiş olabilir - veya iç içe Ürün tipleri, alt Ürün farklılıkları bir haritası durumunda: bu cevap dan kullanım durumları hakkında Genişleyen

def diff(orig: Product, update: Product): Map[Int, Any] = { 
    assert(orig != null && update != null, "Both products must be non-null") 
    assert(orig.getClass == update.getClass, "Both products must be of the same class") 

    val diffs = for (ix <- 0 until orig.productArity) yield { 
    (orig.productElement(ix), update.productElement(ix)) match { 
     case (s1: String, s2: String) if (!s1.equalsIgnoreCase(s2)) => Some((ix -> s2)) 
     case (s1: String, s2: String) => None 
     case (p1: Product, p2: Product) if (p1 != p2) => Some((ix -> diff(p1, p2))) 
     case (x, y) if (x != y) => Some((ix -> y)) 
     case _ => None 
    } 
    } 

    diffs.flatten.toMap 
} 

:

case class A(x: Int, y: String) 
case class B(a: A, b: AnyRef, c: Any) 

val a1 = A(4, "four") 
val a2 = A(4, "Four") 
val a3 = A(4, "quatre") 
val a4 = A(5, "five") 
val b1 = B(a1, null, 6) 
val b2 = B(a1, null, 7) 
val b3 = B(a2, a2, a2) 
val b4 = B(a4, null, 8) 

println(diff(a1, a2)) // Map() 
println(diff(a1, a3)) // Map(0 -> 5) 
println(diff(a1, a4)) // Map(0 -> 5, 1 -> five) 

println(diff(b1, b2)) // Map(2 -> 7) 
println(diff(b1, b3)) // Map(1 -> A(4,four), 2 -> A(4,four)) 
println(diff(b1, b4)) // Map(0 -> Map(0 -> 5, 1 -> five), 2 -> 8l 
24

Belki productIterator ne istediğini geçerli: İstersen unsurları

scala> case class C(x: Int, y: String, z: Char) 
defined class C 

scala> val c1 = C(1, "2", 'c') 
c1: C = C(1,2,c) 

scala> c1.productIterator.toList 
res1: List[Any] = List(1, 2, c) 
5

Ürünün yineleyici kullanabilirsiniz ve maç String.equalsIgnoreCase gibi standart dışı eşitliği kullanmak.

def compare(p1: Product, p2: Product): List[Int] = { 
    assert(p1 != null && p2 != null, "Both products must be non-null") 
    assert(p1.getClass == p2.getClass, "Both products must be of the same class") 

    var idx = List[Int]() 

    for (i <- 0 until p1.productArity) { 
    val equal = (p1.productElement(i), p2.productElement(i)) match { 
     case (s1: String, s2: String) => s1.equalsIgnoreCase(s2) 
     case (x, y) => x == y 
    } 

    if (!equal) idx ::= i 
    } 

    idx.reverse 
} 

Kullanım senaryoları:

case class A(x: Int, y: String) 
case class B(a: A, b: AnyRef, c: Any) 

val a1 = A(4, "four") 
val a2 = A(4, "Four") 
val a3 = A(5, "five") 
val b1 = B(a1, null, 6) 
val b2 = B(a1, null, 7) 
val b3 = B(a2, a2, a2) 

println(compare(a1, a2)) // List() 
println(compare(a1, a3)) // List(0, 1) 

println(compare(b1, b2)) // List(2) 
println(compare(b2, b3)) // List(0, 1, 2) 

// println(compare(a1, b1)) // assertion failed 
İlgili konular