CheddarMonkey
CheddarMonkey

Reputation: 486

Add map elements to list with a loop

I am trying to populate a list with maps created from objects in a query/findAllBy... I always end up with list of maps identical to the last map in the loop.

I have set break points and stepped through the method and found that 1) the data returned from the query is correct, 2) as I step through the loop the data is inserted into the map(s) correctly, 3) the failure comes when inserting the map into the list. All the methods I've used to insert elements into a list (.add, .push, <<, list[(i)] = map, etc) end up overwriting all the previous elements in the list.

Please help. I don't know why this is happening. Hopefully this is an easy one for someone out there.

def shiftRecords = Shift.findAllByUserAndStartTimeBetween( userInstance, startDate, endDate )
ArrayList allShifts = new ArrayList()
LinkedHashMap thisShift = new LinkedHashMap()
def size = shiftRecords.size()

for ( int i = 0; i < size; i++ ){
    thisShift["id"] = shiftRecords[(i)].id
    thisShift["user"] = shiftRecords[(i)].user
    thisShift["startTime"] = shiftRecords[(i)].startTime
    thisShift["posCode"] = shiftRecords[(i)].posCode
    thisShift["deptCode"] = shiftRecords[(i)].deptCode
    thisShift["billingIDX"] = shiftRecords[(i)].billingIDX

    Position thisPos = Position.findByPositionCode( thisShift.posCode )
    thisShift["posTitle"] = thisPos.shortTitle
    thisShift["deptTitle"] = thisPos.departmentTitle

    allShifts.add( (i), thisShift )
}

I need the results of allShifts to be a list of maps with the selected data pulled from the Shift query results. I've tried using shiftRecords.each and eachWithIndex. The problem happens with any type of loop at the point where thisShift map is inserted into allShifts. It doesnt just insert one instance of the map, but replaces all list elements with the current thisShift map.

Upvotes: 3

Views: 2265

Answers (2)

dmahapatro
dmahapatro

Reputation: 50245

def shiftRecords = Shift.findAllByUserAndStartTimeBetween( 
                               userInstance, startDate, endDate )
ArrayList allShifts = new ArrayList()
def size = shiftRecords.size()

for ( int i = 0; i < size; i++ ){
    LinkedHashMap thisShift = new LinkedHashMap()
    thisShift["id"] = shiftRecords[(i)].id
    thisShift["user"] = shiftRecords[(i)].user
    thisShift["startTime"] = shiftRecords[(i)].startTime
    thisShift["posCode"] = shiftRecords[(i)].posCode
    thisShift["deptCode"] = shiftRecords[(i)].deptCode
    thisShift["billingIDX"] = shiftRecords[(i)].billingIDX

    Position thisPos = Position.findByPositionCode( thisShift.posCode )
    thisShift["posTitle"] = thisPos.shortTitle
    thisShift["deptTitle"] = thisPos.departmentTitle

    allShifts << thisShift
}

You need to create a new map each time you iterate over shiftRecords. Although, the above code can be overly simplified in groovy as below:

def shiftRecords = Shift.findAllByUserAndStartTimeBetween( 
                               userInstance, startDate, endDate )
def allShifts = []

shiftRecords.each{
    def thisShift = [:]
    thisShift.id = it.id
    thisShift.user = it.user
    thisShift.startTime = it.startTime
    thisShift.posCode = it.posCode
    thisShift.deptCode = it.deptCode
    thisShift.billingIDX = it.billingIDX

    Position thisPos = Position.findByPositionCode( thisShift.posCode )
    thisShift.posTitle = thisPos.shortTitle
    thisShift.deptTitle = thisPos.departmentTitle

    allShifts << thisShift
}

Upvotes: 3

tim_yates
tim_yates

Reputation: 171084

Try:

def shiftRecords = Shift.findAllByUserAndStartTimeBetween( userInstance, startDate, endDate )
def allShifts = shiftRecords.collect { it ->
    def pos = Position.findByPositionCode( it.posCode )
    [ id         : it.id,
      user       : it.user,
      startTime  : it.startTime,
      posCode    : it.posCode,
      deptCode   : it.deptCode,
      billingIDX : it.billingIDX,
      posTitle   : pos.shortTitle,
      deptTitle  : pos.departmentTitle ]
}

Upvotes: 3

Related Questions