Javascript - 如果列表中已存在具有相同类型的地图,则过滤掉所有地图元素

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

我有一个类型为 Map<number, List<Event>> 的值事件,我正在像这样展平这个值:

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

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"
    }
]

但是,我还想过滤掉所有具有 type = created 的额外元素,这样我最终得到一个只有一个元素的列表,其中 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"
    }
]

我试过这样做:

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

但是,返回的列表与之前相同。 我也试过这个:

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

type === 'created' 过滤掉额外的元素,但也过滤掉其他元素,所以我最后只有这个:

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

我怎样才能做到这一点?

删除重复项仅涉及具有 type = 'created' 的事件,因此,以下内容:

const result = flatEvents.reduce((prev, curr) => {
    return prev.find(e => e.type === "created") ?
        prev :
        [...prev, curr]
}, []
)

我们正在将数组缩减为另一个数组(即过滤但可以访问 prev,在本例中是到目前为止迭代的事件)。对于每个 curr 事件,我们检查 prev 中是否已经存在带有 type=== "created" 的事件,并相应地检查 return。


或者,如果您希望它附加到您之前的操作:

const flatEvents = events
    .valueSeq()
    .flatMap(event => event.values())
    .toList()
    .reduce((prev, curr) =>
        prev.find(e => e.type === "created") ?
            prev :
            [...prev, curr]
        , []
    )

输出
只保留带有 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'
  }
]

您可以使用 filter 并包含一个以 0 开头的本地计数器变量,但在遇到“已创建”类型时递增。这可用于实际过滤:

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);

您可以在 toList() 调用之后链接此 filter() 调用。

为了 O(n) 加上可读性,您始终可以安全地使用 for 循环:

const filterEvents = (events) => {
    let result = [];
    let foundCreatedType = false;
    for (let event of events) {
        if (event.type === "created" && !foundCreatedType) {
            result.push(event)
            foundCreatedType = true;
        } else {
            if (event.type !== "created") result.push(event)
        }
    }
    return result;
}

因此,在您使用 toList() 之后,只需对结果应用 filterEvents