2016-05-12 8 views
2

Вот сценарий определения обновленных данных в обновлении данных. У Seq объектов класса case есть свои идентификаторы, а класс case имеет метод переопределения equals, который выполняет сравнение данных своих атрибутов, исключая поле ID. Чтобы узнать какие-либо обновленные данные, мне нужно получить данные из БД. И требуется сравнение двух последовательностей. Что такое подход Scala для поиска любых обновляемых объектов?Сравнение двух Seq в Scala

Просто подумайте: создайте карту с идентификатором объекта как ключом и объектом в качестве значения. Это может сработать.

(Update) Вот решение, я вышел

val existingDataList: Foo = ... 
val existingDataMap: Map[Long, Foo] = existingDataList.map(d => d.id -> d)(collection.breakOut) 

// To find out updated data  
val updatedData = inputData.filter(d => existingDataMap.get(d.id) != d) 

ответ

3

Итак, у вас есть две коллекции, и вы хотите найти пары объектов в них, имеющие одинаковые идентификаторы, но разные данные, верно? diff на самом деле не то, что вы хотите здесь.

Что-то, как это будет делать:

(first ++ second) 
    .groupBy (_.id) 
    .mapValues (_.toSet) 
    .filterNot { case (_, v) => v.size != 2 } 
    .values 
    .map { v => v.head -> v.last } 

Это даст вам список кортежей, как (первый, второй), где оба элемента имеют один и тот же идентификатор, но разные данные.

Это предполагает, что идентификаторы уникальны в каждой коллекции и каждый идентификатор отображается в обеих коллекциях.

В качестве альтернативы, если вы можете гарантировать, что коллекции имеют одинаковый размер, и содержат точно такой же набор идентификаторов, вы могли бы сделать что-то подобное, что является менее эффективным, но немного проще:

 first.sortBy(_.id) 
     .zip(second.sortBy(_.id)) 
     .filterNot { case (a, b) => a == b } 
+0

Спасибо за показ пары продвинутых подходов. – TeeKai

4

Если я правильно Вас понял, вы уже сделали большую часть тяжелой работы, перекрывая equals - и, конечно, вы MUST также переопределить hashCode соответственно, например:

case class Thing(id:Long, foo:String, bar:Int) { 
    override def equals(that:Any):Boolean = { 
    that match { 
     case Thing(_, f, b) => (f == this.foo) && (b == this.bar) 
     case _ => false 
    } 
    } 

    override def hashCode:Int = { 
    // A quick hack. You probably shouldn't do this for real; 
    // set id to 0 and use the default hashing algorithm: 
    ScalaRunTime._hashCode(this.copy(id = 0)) 
    } 
} 

Теперь определим несколько экземпляров Thing:

val t1 = Thing(111, "t1", 1) 
val t1c = Thing(112, "t1", 1) // Same as t1 but with a new ID 
val t2 = Thing(222, "t2", 2) 
val t3 = Thing(333, "t3", 3) 
val t4 = Thing(444, "t4", 4) 
val t4m = Thing(444, "t4m", 4) // Same as t4 but with a modified "foo" 

Давайте сделаем пару последовательностей:

val orig = Seq(t1, t2, t3, t4) 
val mod = Seq(t1c, t2, t3, t4m) 

А теперь diff говорит нам все, что нужно знать:

mod.diff(orig) 
// => returns Seq(t4m) - just what we wanted 
+0

Это будет работать. И да, я также написал метод hashCode. – TeeKai

Смежные вопросы