brig
brig

Reputation: 3773

Filtering elements based on condition and date filed

I am trying to filter my list based on the below condition.

check if any records with duplicate name and employee fields. If it has duplicates then keep only the element whose date field value is latest and ignoring other duplicate values.

input list:

[{
    name: "Bob",
    employee: "yes",
    date: "10/12/2020"
},
{
    name: "John",
    employee: "no",
    date: "14/12/2020"
},
{
    name: "Bob",
    employee: "yes",
    date: "14/12/2020"
},
{
    name: "Doe",
    employess: "yes",
    date: "10/01/2020"
},
{
    name: "Bob",
    employess: "yes",
    date: "09/12/2020"
},
{
    name: "Doe",
    employee: "yes",
    date: "01/12/2019"
},
{
    name: "Bob",
    employee: "no",
    date: "01/12/2019"
}]

Desirable output:

[{
    name: "Bob",
    employee: "yes",
    date: "14/12/2020"
},
{
    name: "John",
    employee: "no",
    date: "14/12/2020"
},
{
    name: "Bob",
    employee: "no",
    date: "01/12/2019"
},
{
    name: "Doe",
    employess: "yes",
    date: "10/01/2020"
}]

I tried with findAll() method but not able to get desired results.

Upvotes: 0

Views: 59

Answers (3)

cfrick
cfrick

Reputation: 37033

You can groupBy the sub map of name and employee and then find the max date in the values of the grouped items. E.g.

def data = [
    [a: 1, b: 2, c: 0],
    [a: 1, b: 2, c: 3],
    [a: 2, b: 3, c: 0],
]

data.groupBy{
    it.subMap(["a", "b"])
}.collect{ k, v -> 
    k + [c: v*.c.max()] 
}
// -> [[a:1, b:2, c:3], [a:2, b:3, c:0]]

Upvotes: 2

injecteer
injecteer

Reputation: 20699

A simple inject would help:

def list = [[
    name: "Bob",
    employee: "yes",
    date: "10/12/2020"
],
[
    name: "John",
    employee: "no",
    date: "14/12/2020"
],
[
    name: "Bob",
    employee: "yes",
    date: "14/12/2020"
],
[
    name: "Doe",
    employee: "yes",
    date: "10/01/2020"
],
[
    name: "Bob",
    employee: "yes",
    date: "09/12/2020"
],
[
    name: "Doe",
    employee: "yes",
    date: "01/12/2019"
],
[
    name: "Bob",
    employee: "no",
    date: "01/12/2019"
]]

def sdf = new java.text.SimpleDateFormat('dd/MM/yyyy')

def result = list.inject( [:] ){ res, curr ->
  Date date = sdf.parse curr.date
  String key = curr.name + '_' + curr.employee
  if( res[ key ]?.date < date ){
    res[ key ] = curr + [ date:date ]
  }
  res
}.values().collect{ it + [ date:sdf.format( it.date ) ] }.join('\n')

println result

prints

[name:Bob, employee:yes, date:14/12/2020]
[name:John, employee:no, date:14/12/2020]
[name:Doe, employee:yes, date:10/01/2020]
[name:Bob, employee:no, date:01/12/2019]

Upvotes: 1

driversti
driversti

Reputation: 115

As an option, you can collect the initial list as nested maps. For example, first you can group records by name. Then group by an employee. Eventually, you will get the following Map<String, Map<String, List>. Now you can fetch a record by keys in maps and the latest date in the list.

Upvotes: 0

Related Questions