Raymond Holguin
Raymond Holguin

Reputation: 1122

Merging 2 lists while retaining the original data

I wasn't sure how exactly to word the title but this is the situation. I have 2 lists, DBList is a list of DB values and NewList is the new list of values to be stored in the DB. Now the tricky part is that I am only adding values to DBList that don't already exist, BUT if DBList contains values that NewList doesn't then i want to remove them

Essentially, NewList becomes DBList but i want to retain all the applicable previously existing data in DBList that is already persisted to the database

This is what I have and it works, but I want to know if there is a better way to do it.

    List<DeptMajors> DBList;
    List<DeptMajors> NewList;
    for(DeptMajors dm : NewList) {
        if(!DBList.contains(dm)) {
            DBList.add(dm);
        }
    }

    Iterator<DeptMajors> i = DBList.iterator();
    while(i.hasNext()) {
        DeptMajors dm = i.next();
        if(!NewList.contains(dm)) {
            i.remove()
        }
    }

So the first loops puts all data from NewList into DBList that doesn't already exist. Then the next loop will check if DBList contains data that doesn't exist in NewList and removes it from DBList

Upvotes: 2

Views: 117

Answers (1)

tim_yates
tim_yates

Reputation: 171164

Ok, so I had to make up a DeptMajors class:

import groovy.transform.*

@TupleConstructor
@ToString(includeNames=true)
@EqualsAndHashCode(includes=['id'])
class DeptMajors {
    int id
    String name
    int age
}

This class is equal if the id matches (and no other fields)

We can then make a dbList (lower case initial char for variables, else Groovy can sometimes get confused and think it's a class)

def dbList = [
    new DeptMajors(1, 'tim', 21),
    new DeptMajors(2, 'raymond', 20)
]

And a newList which contains an updated raymond (which will be ignored), a new entry alice (which will be added) and no tim (so that will be removed)

def newList = [
    new DeptMajors(2, 'raymond', 30),
    new DeptMajors(3, 'alice', 28)
]

We can then work out our new merged list. This is the intersection of dbList and newList (so we keep raymond in the original state), added to the new elements in newList which can be found by taking dbList away from it:

def mergedList = dbList.intersect(newList) + (newList - dbList)

This give the result I think you want?

assert mergedList == [
    new DeptMajors(2, 'raymond', 20),  // unchanged
    new DeptMajors(3, 'alice', 28)     // new entry (tim is removed)
]

Edit

Or as BZ says in the comments, you could also use:

def mergedList = newList.collect { e -> dbList.contains(e) ? dbList.find { it == e }: e}

Or the shorter:

def mergedList = newList.collect { e -> dbList.find { it == e } ?: e}

Upvotes: 2

Related Questions