javascriptimmutable.js

Javascript - Filtering out all map elements if a map with the same type already exists in a list


I have a value events of a type Map<number, List<Event>>, I am flattening this value like this:

const flatEvents = events.valueSeq().flatMap(event => event.values()).toList()

The value flatEvents looks like this after flattening:

[
    {
        "eventTime": "2022-03-18T08:04:00Z",
        "type": "deviated",
        "id": 841,
        "createdAt": "2022-03-18T08:04:43.975332Z",
        "createdBy": "47"
    },
    {
        "eventTime": "2022-03-15T11:11:38.220966Z",
        "type": "created",
        "id": 826,
        "createdAt": "2022-03-15T11:11:38.220966Z",
        "createdBy": "47"
    },
    {
        "eventTime": "2022-03-15T11:11:38.220966Z",
        "id": 827,
        "type": "created",
        "createdAt": "2022-03-15T11:11:38.220966Z",
        "createdBy": "47"
    },
    {
        "eventTime": "2022-03-15T11:11:38.220966Z",
        "type": "created",
        "id": 828,
        "createdAt": "2022-03-15T11:11:38.220966Z",
        "createdBy": "47"
    }
]

But, I would also like to filter out all the extra elements that have type = created, so that I end up with a list that has only one element where type == created:

[
    {
        "eventTime": "2022-03-18T08:04:00Z",
        "type": "deviated",
        "id": 841,
        "createdAt": "2022-03-18T08:04:43.975332Z",
        "createdBy": "47"
    },
    {
        "eventTime": "2022-03-15T11:11:38.220966Z",
        "type": "created",
        "id": 826,
        "createdAt": "2022-03-15T11:11:38.220966Z",
        "createdBy": "47"
    }
]

I have tried to do it like this:

const flatEvents = events.valueSeq()
    .flatMap(event => event.values()).toList()
    .filter((v, _, list) =>
      list.find(v => v.get('type') === 'created'))

But, that is returning the same list as before. I have also tried this:

const flatEvents = events.valueSeq()
    .flatMap(event => event.values()).toList()
    .filter((_,i,flattenedEvents) =>
      flattenedEvents.findIndex(consignmentEvent => (consignmentEvent.get('type') === 'created')) === i
    )

That filters out extra elements with the type === 'created', but also other elements, so I end up with only this:

[
    {
        "eventTime": "2022-03-18T08:04:00Z",
        "type": "deviated",
        "id": 841,
        "createdAt": "2022-03-18T08:04:43.975332Z",
        "createdBy": "47"
    },
 ]

How can I achieve this?


Solution

  • You can use filter and include a local counter variable that starts with 0, but is incremented when a "created" type is encountered. This can be used for the actual filtering:

    let flatEvents = [{"eventTime": "2022-03-18T08:04:00Z","type": "deviated","id": 841,"createdAt": "2022-03-18T08:04:43.975332Z","createdBy": "47"},{"eventTime": "2022-03-15T11:11:38.220966Z","type": "created","id": 826,"createdAt": "2022-03-15T11:11:38.220966Z","createdBy": "47"},{"eventTime": "2022-03-15T11:11:38.220966Z","id": 827,"type": "created","createdAt": "2022-03-15T11:11:38.220966Z","createdBy": "47"},{"eventTime": "2022-03-15T11:11:38.220966Z","type": "created","id": 828,"createdAt": "2022-03-15T11:11:38.220966Z","createdBy": "47"}];
    
    flatEvents = flatEvents.filter(
       (count => 
            event => event.type != "created" || !count++
       )(0)
    ); 
    
    console.log(flatEvents);

    You would chain this filter() call after your toList() call.