immutable.js 过滤和变异(删除)找到的条目
Posted
技术标签:
【中文标题】immutable.js 过滤和变异(删除)找到的条目【英文标题】:immutable.js filter and mutate (remove) found entries 【发布时间】:2017-04-06 12:18:15 【问题描述】:我有两个循环,一个用于一个月中的每一天,另一个用于本月的所有事件。假设我有 100 000 个事件。
我正在寻找一种方法从主要事件List
中删除事件,一旦它们被“消耗”。
代码是这样的:
const calendarRange = [initialDate, initialDate, initialDate, initialDate, ...] // say we have 30 dates, one for each day
const events = fromJS([initialDate, initialDate, initialDate, ...]) // let's say we have 100 000
calendarRange.map((day) =>
const dayEvents = events.filter((event) => day.get('initialDate').isSame(event.get('initialDate'), 'day')) // we get all events for each day
doSomeThingWithDays(dayEvents)
// how could I subtract `dayEvents` from `events` in a way
// the next celandarRange iteration we have less events to filter?
// the order of the first loop must be preserved (because it's from day 1 to day 301])
使用 lodash 我可以做类似的事情:
calendarRange.map((day) =>
const dayEvents = events.filter((event) => day.get('initialDate').isSame(event.get('initialDate'), 'day')) // we get all events for each day
doSomeThingWithDays(dayEvents)
pullAllWith(events, dayEvents, (a, b) => a === b)
如何用 immutablejs 完成同样的优化?我并不是真的期待我的迭代列表方式的解决方案,而是一种智能的方式来减少事件List
,使其变得越来越小..
【问题讨论】:
【参考方案1】:您可以尝试Map
将事件拆分为垃圾箱-根据您的示例,您可以根据日期进行垃圾箱-您可以查找垃圾箱,将其作为批处理并将其删除 O(1)。不可变映射相当便宜,而且比遍历列表要好得多。您可能会产生一次性分箱的成本,但可以通过 O(1) 查找来分期付款。
可能是这样的:
eventbins = OrderedMap(events.groupBy(evt => evt.get('initialDate').dayOfYear() /* or whatever selector */))
function iter(list, bins)
if(list.isEmpty())
return
day = list.first()
dayEvents = bins.get(day.dayOfYear())
doSomeThingWithDays(dayEvents)
iter(list.shift(), bins.delete(day))
iter(rangeOfDays, eventbins)
【讨论】:
顺便说一句,我应该补充一点,该方法是纯函数式的,具有零副作用并使用尾递归。如果你想,说其余的项目,你可以简单地从iter
返回一个值。【参考方案2】:
通过移除已经处理过的元素,你不会让任何事情变得更快。所有过滤器操作的成本平均会减半,但是在每次迭代中构建新列表会花费你一些 cpu 周期,因此它不会显着加快(在大 O 意义上)。相反,您可以基于 initialDate
-s 构建索引,例如不可变映射,从而使所有 filter
调用变得不必要。
const calendarRange = Immutable.Range(0, 10, 2).map(i => Immutable.fromJS(initialDate: i));
const events = Immutable.Range(0, 20).map(i => Immutable.fromJS(initialDate: i%10, i:i));
const index = events.groupBy(event => event.get('initialDate'));
calendarRange.forEach(day =>
const dayEvents = index.get(day.get('initialDate'));
doSomeThingWithDays(dayEvents);
);
function doSomeThingWithDays(data)
console.log(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>
【讨论】:
以上是关于immutable.js 过滤和变异(删除)找到的条目的主要内容,如果未能解决你的问题,请参考以下文章
使用过滤器/变异和 dplyr/tidyverse 逻辑对数据库进行分类[重复]
使用 immutable.js 和 Facebook 流进行静态类型检查